server: Extend the Annotations framework (#5103)

* Extend addAnnotation and listAnnotations APIs

* Allow users to add, list and remove comments

* Add adminsonly UI and allow admins or owners to remove comments

* New annotations tab

* In progress: new comments section

* Address review comments

* Fix

* Fix annotationfilter and comments section

* Add keyword and delete action

* Fix and rename annotations tab

* Update annotation visibility API and update comments table accordingly

* Allow users seeing all the comments for their owned resources

* Extend comments for volumes and snapshots

* Extend comments to multiple entities

* Add uuid to ssh keypairs

* SSH keypair UI refactor

* Extend comments to the infrastructure entities

* Add missing entities

* Fix upgrade version for ssh keypairs

* Fix typo on DB upgrade schema

* Fix annotations table columns when there is no data

* Extend the list view of items showing they if they have comments

* Remove extra test

* Add annotation permissions

* Address review comments

* Extend marvin tests for annotations

* updating ui stuff

* addition to toggle visibility

* Fix pagination on comments section

* Extend to kubernetes clusters

* Fixes after last review

* Change default value for adminsonly column

* Remove the required field for the annotationfilter parameter

* Small fixes on visibility and other fixes

* Cleanup to reduce files changed

* Rollback extra line

* Address review comments

* Fix cleanup error on smoke test

* Fix sending incorrect parameter to checkPermissions method

* Add check domain access for the calling account for domain networks

* Fix only display annotations icon if there are comments the user can see

* Simply change the Save button label to Submit

* Change order of the Tools menu to provent users getting 404 error on clicking the text instead of expanding

* Remove comments when removing entities

* Address review comments on marvin tests

* Allow users to list annotations for an entity ID

* Allow users to see all comments for allowed entities

* Fix search filters

* Remove username from search filter

* Add pagination to the annotations tab

* Display username for user comments

* Fix add permissions for domain and resource admins

* Fix for domain admins

* Trivial but important UI fix

* Replace pagination for annotations tab

* Add confirmation for delete comment

* Lint warnings

* Fix reduced list as domain admin

* Fix display remove comment button for non admins

* Improve display remove action button

* Remove unused parameter on groupShow

* Include a clock icon to the all comments filter except for root admin

* Move cleanup SQL to the correct file after rebasing main

Co-authored-by: davidjumani <dj.davidjumani1994@gmail.com>
This commit is contained in:
Nicolas Vazquez 2021-09-08 01:44:06 -03:00 committed by GitHub
parent 10c49a6ad3
commit 413d10dd81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
150 changed files with 2492 additions and 336 deletions

View File

@ -0,0 +1,25 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.kubernetes.cluster;
import com.cloud.utils.component.Adapter;
import org.apache.cloudstack.acl.ControlledEntity;
public interface KubernetesClusterHelper extends Adapter {
ControlledEntity findByUuid(String uuid);
}

View File

@ -106,4 +106,9 @@ public class StaticRouteProfile implements StaticRoute {
public Class<?> getEntityType() {
return StaticRoute.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -17,9 +17,10 @@
package com.cloud.user;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface SSHKeyPair extends ControlledEntity, InternalIdentity {
public interface SSHKeyPair extends ControlledEntity, InternalIdentity, Identity {
/**
* @return The given name of the key pair.

View File

@ -30,4 +30,5 @@ public interface ControlledEntity extends OwnedBy, PartOf {
}
Class<?> getEntityType();
String getName();
}

View File

@ -16,27 +16,46 @@
// under the License.
package org.apache.cloudstack.annotation;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.command.admin.annotation.AddAnnotationCmd;
import org.apache.cloudstack.api.command.admin.annotation.ListAnnotationsCmd;
import org.apache.cloudstack.api.command.admin.annotation.RemoveAnnotationCmd;
import org.apache.cloudstack.api.command.admin.annotation.UpdateAnnotationVisibilityCmd;
import org.apache.cloudstack.api.response.AnnotationResponse;
import org.apache.cloudstack.api.response.ListResponse;
import java.util.ArrayList;
import java.util.List;
public interface AnnotationService {
ListResponse<AnnotationResponse> searchForAnnotations(ListAnnotationsCmd cmd);
AnnotationResponse addAnnotation(AddAnnotationCmd addAnnotationCmd);
AnnotationResponse addAnnotation(String text, EntityType type, String uuid);
AnnotationResponse addAnnotation(String text, EntityType type, String uuid, boolean adminsOnly);
AnnotationResponse removeAnnotation(RemoveAnnotationCmd removeAnnotationCmd);
enum EntityType {
HOST("host"), DOMAIN("domain"), VM("vm_instance");
private String tableName;
AnnotationResponse updateAnnotationVisibility(UpdateAnnotationVisibilityCmd cmd);
EntityType(String tableName) {
this.tableName = tableName;
enum EntityType {
VM(true), VOLUME(true), SNAPSHOT(true),
VM_SNAPSHOT(true), INSTANCE_GROUP(true), SSH_KEYPAIR(true),
NETWORK(true), VPC(true), PUBLIC_IP_ADDRESS(true), VPN_CUSTOMER_GATEWAY(true),
TEMPLATE(true), ISO(true), KUBERNETES_CLUSTER(true),
SERVICE_OFFERING(false), DISK_OFFERING(false), NETWORK_OFFERING(false),
ZONE(false), POD(false), CLUSTER(false), HOST(false), DOMAIN(false),
PRIMARY_STORAGE(false), SECONDARY_STORAGE(false), VR(false), SYSTEM_VM(false);
private final boolean usersAllowed;
public boolean isUserAllowed() {
return this.usersAllowed;
}
EntityType(boolean usersAllowed) {
this.usersAllowed = usersAllowed;
}
static public boolean contains(String representation) {
try {
/* EntityType tiep = */ valueOf(representation);
@ -45,5 +64,24 @@ public interface AnnotationService {
return false;
}
}
static public List<EntityType> getNotAllowedTypesForNonAdmins(RoleType roleType) {
List<EntityType> list = new ArrayList<>();
list.add(EntityType.NETWORK_OFFERING);
list.add(EntityType.ZONE);
list.add(EntityType.POD);
list.add(EntityType.CLUSTER);
list.add(EntityType.HOST);
list.add(EntityType.PRIMARY_STORAGE);
list.add(EntityType.SECONDARY_STORAGE);
list.add(EntityType.VR);
list.add(EntityType.SYSTEM_VM);
if (roleType != RoleType.DomainAdmin) {
list.add(EntityType.DOMAIN);
list.add(EntityType.SERVICE_OFFERING);
list.add(EntityType.DISK_OFFERING);
}
return list;
}
}
}

View File

@ -742,6 +742,7 @@ public class ApiConstants {
public static final String IAM_GROUPS = "groups";
public static final String ENTITY_TYPE = "entitytype";
public static final String ENTITY_ID = "entityid";
public static final String ENTITY_NAME = "entityname";
public static final String EXTERNAL_ID = "externalid";
public static final String ACCESS_TYPE = "accesstype";
@ -793,7 +794,7 @@ public class ApiConstants {
+ " \"{<algorithm>}\", not including the double quotes. In this <algorithm> is the exact string\n"
+ " representing the java supported algorithm, i.e. MD5 or SHA-256. Note that java does not\n" + " contain an algorithm called SHA256 or one called sha-256, only SHA-256.";
public static final String HAS_ANNOTATION = "hasannotation";
public static final String HAS_ANNOTATIONS = "hasannotations";
public static final String LAST_ANNOTATED = "lastannotated";
public static final String LDAP_DOMAIN = "ldapdomain";
@ -844,7 +845,10 @@ public class ApiConstants {
public static final String SOURCETEMPLATEID = "sourcetemplateid";
public static final String DYNAMIC_SCALING_ENABLED = "dynamicscalingenabled";
public static final String POOL_TYPE ="pooltype";
public static final String POOL_TYPE = "pooltype";
public static final String ADMINS_ONLY = "adminsonly";
public static final String ANNOTATION_FILTER = "annotationfilter";
public enum BootType {
UEFI, BIOS;

View File

@ -0,0 +1,35 @@
// 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;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public abstract class BaseResponseWithAnnotations extends BaseResponse {
@SerializedName(ApiConstants.HAS_ANNOTATIONS)
@Param(description = "true if the entity/resource has annotations")
private Boolean hasAnnotation;
public Boolean hasAnnotation() {
return hasAnnotation;
}
public void setHasAnnotation(Boolean hasAnnotation) {
this.hasAnnotation = hasAnnotation;
}
}

View File

@ -23,7 +23,7 @@ import org.apache.cloudstack.api.response.ResourceTagResponse;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public abstract class BaseResponseWithTagInformation extends BaseResponse {
public abstract class BaseResponseWithTagInformation extends BaseResponseWithAnnotations {
@SerializedName(ApiConstants.TAGS)
@Param(description = "the list of resource tags associated", responseObject = ResourceTagResponse.class)

View File

@ -31,6 +31,7 @@ import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AnnotationResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.lang3.BooleanUtils;
@APICommand(name = AddAnnotationCmd.APINAME, description = "add an annotation.", responseObject = AnnotationResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.11", authorized = {RoleType.Admin})
@ -40,11 +41,17 @@ public class AddAnnotationCmd extends BaseCmd {
@Parameter(name = ApiConstants.ANNOTATION, type = CommandType.STRING, description = "the annotation text")
private String annotation;
@Parameter(name = ApiConstants.ENTITY_TYPE, type = CommandType.STRING, description = "the entity type (only HOST is allowed atm)")
private String entityType;
@Parameter(name = ApiConstants.ENTITY_ID, type = CommandType.STRING, description = "the id of the entity to annotate")
private String entityUuid;
@Parameter(name = ApiConstants.ADMINS_ONLY, type = CommandType.BOOLEAN, since = "4.16.0",
description = "the annotation is visible for admins only")
private Boolean adminsOnly;
public String getAnnotation() {
return annotation;
}
@ -63,6 +70,10 @@ public class AddAnnotationCmd extends BaseCmd {
return entityUuid;
}
public boolean isAdminsOnly() {
return BooleanUtils.toBoolean(adminsOnly);
}
@Override
public void execute()
throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,

View File

@ -41,11 +41,24 @@ public class ListAnnotationsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.STRING, description = "the id of the annotation")
private String uuid;
@Parameter(name = ApiConstants.ENTITY_TYPE, type = CommandType.STRING, description = "the entity type")
private String entityType;
@Parameter(name = ApiConstants.ENTITY_ID, type = CommandType.STRING, description = "the id of the entity for which to show annotations")
private String entityUuid;
@Parameter(name = ApiConstants.USER_ID, type = CommandType.STRING, since = "4.16.0",
description = "optional: the id of the user of the annotation", required = false)
private String userUuid;
@Parameter(name = ApiConstants.ANNOTATION_FILTER,
type = CommandType.STRING, since = "4.16.0",
description = "possible values are \"self\" and \"all\". "
+ "* self : annotations that have been created by the calling user. "
+ "* all : all the annotations the calling user can access")
private String annotationFilter;
public String getUuid() {
return uuid;
}
@ -58,6 +71,14 @@ public class ListAnnotationsCmd extends BaseListCmd {
return entityUuid;
}
public String getUserUuid() {
return userUuid;
}
public String getAnnotationFilter() {
return annotationFilter;
}
@Override public void execute()
throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException,
NetworkRuleConflictException {

View File

@ -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.api.command.admin.annotation;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AnnotationResponse;
import org.apache.cloudstack.context.CallContext;
@APICommand(name = UpdateAnnotationVisibilityCmd.APINAME, description = "update an annotation visibility.",
responseObject = AnnotationResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
since = "4.16", authorized = {RoleType.Admin})
public class UpdateAnnotationVisibilityCmd extends BaseCmd {
public static final String APINAME = "updateAnnotationVisibility";
@Parameter(name = ApiConstants.ID, type = CommandType.STRING, required = true,
description = "the id of the annotation")
private String uuid;
@Parameter(name = ApiConstants.ADMINS_ONLY, type = CommandType.BOOLEAN, required = true,
description = "the annotation is visible for admins only")
private Boolean adminsOnly;
public String getUuid() {
return uuid;
}
public Boolean getAdminsOnly() {
return adminsOnly;
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
AnnotationResponse annotationResponse = annotationService.updateAnnotationVisibility(this);
annotationResponse.setResponseName(getCommandName());
this.setResponseObject(annotationResponse);
}
@Override
public String getCommandName() {
return String.format("%s%s", APINAME.toLowerCase(), BaseCmd.RESPONSE_SUFFIX);
}
@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccount().getAccountId();
}
}

View File

@ -124,7 +124,7 @@ public class UpdateHostCmd extends BaseCmd {
try {
result = _resourceService.updateHost(this);
if(getAnnotation() != null) {
annotationService.addAnnotation(getAnnotation(), AnnotationService.EntityType.HOST, result.getUuid());
annotationService.addAnnotation(getAnnotation(), AnnotationService.EntityType.HOST, result.getUuid(), true);
}
HostResponse hostResponse = _responseGenerator.createHostResponse(result);
hostResponse.setResponseName(getCommandName());

View File

@ -384,4 +384,9 @@ public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements F
return FirewallRule.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -358,4 +358,9 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
return FirewallRule.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -447,4 +447,9 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
return FirewallRule.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -333,4 +333,9 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
return FirewallRule.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -43,6 +43,10 @@ public class AnnotationResponse extends BaseResponse {
@Param(description = "the (uu)id of the entitiy to which this annotation pertains")
private String entityUuid;
@SerializedName(ApiConstants.ENTITY_NAME)
@Param(description = "the name of the entitiy to which this annotation pertains")
private String entityName;
@SerializedName(ApiConstants.ANNOTATION)
@Param(description = "the contents of the annotation")
private String annotation;
@ -51,6 +55,14 @@ public class AnnotationResponse extends BaseResponse {
@Param(description = "The (uu)id of the user that entered the annotation")
private String userUuid;
@SerializedName(ApiConstants.USERNAME)
@Param(description = "The username of the user that entered the annotation")
private String username;
@SerializedName(ApiConstants.ADMINS_ONLY)
@Param(description = "True if the annotation is available for admins only")
private Boolean adminsOnly;
@SerializedName(ApiConstants.CREATED)
@Param(description = "the creation timestamp for this annotation")
private Date created;
@ -118,4 +130,28 @@ public class AnnotationResponse extends BaseResponse {
public void setRemoved(Date removed) {
this.removed = removed;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Boolean getAdminsOnly() {
return adminsOnly;
}
public void setAdminsOnly(Boolean adminsOnly) {
this.adminsOnly = adminsOnly;
}
public String getEntityName() {
return entityName;
}
public void setEntityName(String entityName) {
this.entityName = entityName;
}
}

View File

@ -22,7 +22,7 @@ import java.util.List;
import java.util.Map;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.org.Cluster;
@ -30,7 +30,7 @@ import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@EntityReference(value = Cluster.class)
public class ClusterResponse extends BaseResponse {
public class ClusterResponse extends BaseResponseWithAnnotations {
@SerializedName(ApiConstants.ID)
@Param(description = "the cluster ID")
private String id;

View File

@ -28,8 +28,8 @@ public class CreateSSHKeyPairResponse extends SSHKeyPairResponse {
public CreateSSHKeyPairResponse() {
}
public CreateSSHKeyPairResponse(String name, String fingerprint, String privateKey) {
super(name, fingerprint);
public CreateSSHKeyPairResponse(String uuid, String name, String fingerprint, String privateKey) {
super(uuid, name, fingerprint);
this.privateKey = privateKey;
}

View File

@ -19,7 +19,7 @@ package org.apache.cloudstack.api.response;
import java.util.Date;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.offering.DiskOffering;
@ -27,7 +27,7 @@ import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@EntityReference(value = DiskOffering.class)
public class DiskOfferingResponse extends BaseResponse {
public class DiskOfferingResponse extends BaseResponseWithAnnotations {
@SerializedName(ApiConstants.ID)
@Param(description = "unique ID of the disk offering")
private String id;

View File

@ -19,7 +19,7 @@ package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.domain.Domain;
@ -28,7 +28,7 @@ import com.cloud.serializer.Param;
import java.util.Date;
@EntityReference(value = Domain.class)
public class DomainResponse extends BaseResponse implements ResourceLimitAndCountResponse {
public class DomainResponse extends BaseResponseWithAnnotations implements ResourceLimitAndCountResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the domain")
private String id;

View File

@ -22,7 +22,7 @@ import java.util.List;
import java.util.Set;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.serializer.Param;
@ -32,7 +32,7 @@ import com.google.gson.annotations.SerializedName;
@EntityReference(value = VirtualMachine.class)
@SuppressWarnings("unused")
public class DomainRouterResponse extends BaseResponse implements ControlledViewEntityResponse {
public class DomainRouterResponse extends BaseResponseWithAnnotations implements ControlledViewEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the id of the router")
private String id;

View File

@ -22,7 +22,7 @@ import java.util.List;
import java.util.Map;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import org.apache.cloudstack.ha.HAConfig;
import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
@ -34,7 +34,7 @@ import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@EntityReference(value = Host.class)
public class HostResponse extends BaseResponse {
public class HostResponse extends BaseResponseWithAnnotations {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the host")
private String id;

View File

@ -21,7 +21,7 @@ import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.IpAddress;
@ -30,7 +30,7 @@ import com.google.gson.annotations.SerializedName;
@EntityReference(value = IpAddress.class)
@SuppressWarnings("unused")
public class IPAddressResponse extends BaseResponse implements ControlledEntityResponse {
public class IPAddressResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "public IP address id")
private String id;

View File

@ -17,7 +17,7 @@
package org.apache.cloudstack.api.response;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.serializer.Param;
@ -26,7 +26,7 @@ import com.cloud.storage.ScopeType;
import com.google.gson.annotations.SerializedName;
@EntityReference(value = ImageStore.class)
public class ImageStoreResponse extends BaseResponse {
public class ImageStoreResponse extends BaseResponseWithAnnotations {
@SerializedName("id")
@Param(description = "the ID of the image store")
private String id;

View File

@ -21,7 +21,7 @@ import java.util.Date;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.serializer.Param;
@ -29,7 +29,7 @@ import com.cloud.vm.InstanceGroup;
@SuppressWarnings("unused")
@EntityReference(value = InstanceGroup.class)
public class InstanceGroupResponse extends BaseResponse implements ControlledViewEntityResponse {
public class InstanceGroupResponse extends BaseResponseWithAnnotations implements ControlledViewEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the ID of the instance group")

View File

@ -21,7 +21,7 @@ import java.util.List;
import java.util.Map;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.offering.NetworkOffering;
@ -30,7 +30,7 @@ import com.google.gson.annotations.SerializedName;
@EntityReference(value = NetworkOffering.class)
@SuppressWarnings("unused")
public class NetworkOfferingResponse extends BaseResponse {
public class NetworkOfferingResponse extends BaseResponseWithAnnotations {
@SerializedName("id")
@Param(description = "the id of the network offering")
private String id;

View File

@ -23,7 +23,7 @@ import java.util.Set;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.Network;
@ -33,7 +33,7 @@ import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
@EntityReference(value = {Network.class, ProjectAccount.class})
public class NetworkResponse extends BaseResponse implements ControlledEntityResponse {
public class NetworkResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the id of the network")

View File

@ -21,14 +21,14 @@ import java.util.List;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.dc.Pod;
import com.cloud.serializer.Param;
@EntityReference(value = Pod.class)
public class PodResponse extends BaseResponse {
public class PodResponse extends BaseResponseWithAnnotations {
@SerializedName("id")
@Param(description = "the ID of the Pod")
private String id;

View File

@ -19,11 +19,15 @@ package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
public class SSHKeyPairResponse extends BaseResponse {
public class SSHKeyPairResponse extends BaseResponseWithAnnotations {
@SerializedName(ApiConstants.ID)
@Param(description = "ID of the ssh keypair")
private String id;
@SerializedName(ApiConstants.NAME)
@Param(description = "Name of the keypair")
@ -45,7 +49,8 @@ public class SSHKeyPairResponse extends BaseResponse {
public SSHKeyPairResponse() {
}
public SSHKeyPairResponse(String name, String fingerprint) {
public SSHKeyPairResponse(String uuid, String name, String fingerprint) {
this.id = uuid;
this.name = name;
this.fingerprint = fingerprint;
}
@ -89,4 +94,12 @@ public class SSHKeyPairResponse extends BaseResponse {
public void setDomainName(String domain) {
this.domain = domain;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

View File

@ -20,7 +20,7 @@ import java.util.Date;
import java.util.Map;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.offering.ServiceOffering;
@ -28,7 +28,7 @@ import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@EntityReference(value = ServiceOffering.class)
public class ServiceOfferingResponse extends BaseResponse {
public class ServiceOfferingResponse extends BaseResponseWithAnnotations {
@SerializedName("id")
@Param(description = "the id of the service offering")
private String id;

View File

@ -21,7 +21,7 @@ import java.util.Date;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.Site2SiteCustomerGateway;
@ -29,7 +29,7 @@ import com.cloud.serializer.Param;
@EntityReference(value = Site2SiteCustomerGateway.class)
@SuppressWarnings("unused")
public class Site2SiteCustomerGatewayResponse extends BaseResponse implements ControlledEntityResponse {
public class Site2SiteCustomerGatewayResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the vpn gateway ID")
private String id;

View File

@ -21,14 +21,14 @@ import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import java.util.Date;
import java.util.Map;
@EntityReference(value = StoragePool.class)
public class StoragePoolResponse extends BaseResponse {
public class StoragePoolResponse extends BaseResponseWithAnnotations {
@SerializedName("id")
@Param(description = "the ID of the storage pool")
private String id;

View File

@ -20,7 +20,7 @@ import java.util.Date;
import java.util.List;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.host.Status;
@ -29,7 +29,7 @@ import com.cloud.vm.VirtualMachine;
import com.google.gson.annotations.SerializedName;
@EntityReference(value = VirtualMachine.class)
public class SystemVmResponse extends BaseResponse {
public class SystemVmResponse extends BaseResponseWithAnnotations {
@SerializedName("id")
@Param(description = "the ID of the system VM")
private String id;

View File

@ -21,7 +21,7 @@ import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.vpc.Vpc;
@ -30,7 +30,7 @@ import com.google.gson.annotations.SerializedName;
@EntityReference(value = Vpc.class)
@SuppressWarnings("unused")
public class VpcResponse extends BaseResponse implements ControlledEntityResponse {
public class VpcResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse {
@SerializedName("id")
@Param(description = "the id of the VPC")
private String id;

View File

@ -23,7 +23,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.dc.DataCenter;
@ -32,7 +32,7 @@ import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
@EntityReference(value = DataCenter.class)
public class ZoneResponse extends BaseResponse {
public class ZoneResponse extends BaseResponseWithAnnotations {
@SerializedName(ApiConstants.ID)
@Param(description = "Zone id")
private String id;

View File

@ -332,4 +332,7 @@
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
</bean>
<bean id="kubernetesClusterHelperRegistry"
class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry">
</bean>
</beans>

View File

@ -0,0 +1,21 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
name=kubernetes
parent=compute

View File

@ -0,0 +1,32 @@
<!--
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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>
<bean class="org.apache.cloudstack.spring.lifecycle.registry.RegistryLifecycle">
<property name="registry" ref="kubernetesClusterHelperRegistry" />
<property name="typeClass" value="com.cloud.kubernetes.cluster.KubernetesClusterHelper" />
</bean>
</beans>

View File

@ -255,6 +255,11 @@ public class PublicIp implements PublicIpAddress {
return IpAddress.class;
}
@Override
public String getName() {
return _addr.getName();
}
@Override
public State getRuleState() {
return _addr.getRuleState();

View File

@ -158,4 +158,9 @@ public class StaticNatRuleImpl implements StaticNatRule {
public Class<?> getEntityType() {
return FirewallRule.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -45,6 +45,8 @@ import javax.naming.ConfigurationException;
import com.cloud.api.ApiDBUtils;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd;
import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin;
@ -368,6 +370,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
private NetworkOfferingDao networkOfferingDao;
@Inject
private DomainRouterJoinDao domainRouterJoinDao;
@Inject
private AnnotationDao annotationDao;
VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
@ -627,6 +631,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
// Remove deploy as-is (if any)
userVmDeployAsIsDetailsDao.removeDetails(vm.getId());
// Remove comments (if any)
annotationDao.removeByEntityType(AnnotationService.EntityType.VM.name(), vm.getUuid());
// send hypervisor-dependent commands before removing
final List<Command> finalizeExpungeCommands = hvGuru.finalizeExpunge(vm);
if (finalizeExpungeCommands != null && finalizeExpungeCommands.size() > 0) {

View File

@ -48,6 +48,8 @@ import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
import org.apache.cloudstack.context.CallContext;
@ -317,6 +319,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
@Inject
ResourceManager resourceManager;
@Inject
private AnnotationDao annotationDao;
List<NetworkGuru> networkGurus;
@ -3673,6 +3677,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
throw new CloudRuntimeException("We should never get to here because we used true when applyIpAssociations", e);
}
annotationDao.removeByEntityType(AnnotationService.EntityType.NETWORK.name(), network.getUuid());
return success;
}

View File

@ -224,4 +224,9 @@ public class EventVO implements Event {
public Class<?> getEntityType() {
return Event.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -189,4 +189,9 @@ public class UserIpv6AddressVO implements UserIpv6Address {
public Class<?> getEntityType() {
return UserIpv6Address.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -130,4 +130,9 @@ public class VpnUserVO implements VpnUser {
public Class<?> getEntityType() {
return VpnUser.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -156,4 +156,9 @@ public class AutoScalePolicyVO implements AutoScalePolicy, InternalIdentity {
return AutoScalePolicy.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -229,4 +229,9 @@ public class AutoScaleVmGroupVO implements AutoScaleVmGroup, InternalIdentity {
public Class<?> getEntityType() {
return AutoScaleVmGroup.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -238,4 +238,9 @@ public class AutoScaleVmProfileVO implements AutoScaleVmProfile, Identity, Inter
return AutoScaleVmProfile.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -133,4 +133,9 @@ public class ConditionVO implements Condition, Identity, InternalIdentity {
return Condition.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -366,6 +366,11 @@ public class IPAddressVO implements IpAddress {
return IpAddress.class;
}
@Override
public String getName() {
return address.addr();
}
@Override
public Date getRemoved() {
return removed;

View File

@ -121,4 +121,9 @@ public class MonitoringServiceVO implements MonitoringService {
public Class<?> getEntityType() {
return MonitoringService.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -170,4 +170,9 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn {
public Class<?> getEntityType() {
return RemoteAccessVpn.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -177,4 +177,9 @@ public class Site2SiteVpnConnectionVO implements Site2SiteVpnConnection, Interna
public Class<?> getEntityType() {
return Site2SiteVpnConnection.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -134,4 +134,9 @@ public class Site2SiteVpnGatewayVO implements Site2SiteVpnGateway {
public Class<?> getEntityType() {
return Site2SiteVpnGateway.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -308,4 +308,9 @@ public class FirewallRuleVO implements FirewallRule {
public Class<?> getEntityType() {
return FirewallRule.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -140,4 +140,9 @@ public class StaticRouteVO implements StaticRoute {
public Class<?> getEntityType() {
return StaticRoute.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -221,6 +221,11 @@ public class VpcGatewayVO implements VpcGateway {
return VpcGateway.class;
}
@Override
public String getName() {
return null;
}
public void setVpcId(Long vpcId) {
this.vpcId = vpcId;
}

View File

@ -187,4 +187,9 @@ public class ProjectInvitationVO implements ProjectInvitation {
public Class<?> getEntityType() {
return ProjectInvitation.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -171,4 +171,9 @@ public class ResourceTagVO implements ResourceTag {
public Class<?> getEntityType() {
return ResourceTag.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -64,6 +64,32 @@ public class Upgrade41520to41600 implements DbUpgrade, DbUpgradeSystemVmTemplate
@Override
public void performDataMigration(Connection conn) {
generateUuidForExistingSshKeyPairs(conn);
}
private void generateUuidForExistingSshKeyPairs(Connection conn) {
LOG.debug("Generating uuid for existing ssh key-pairs");
try {
PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM `cloud`.`ssh_keypairs` WHERE uuid is null");
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
long sshKeyId = rs.getLong(1);
pstmt = conn.prepareStatement("UPDATE `cloud`.`ssh_keypairs` SET `uuid` = UUID() WHERE id = ?");
pstmt.setLong(1, sshKeyId);
pstmt.executeUpdate();
}
if (!rs.isClosed()) {
rs.close();
}
if (!pstmt.isClosed()) {
pstmt.close();
}
LOG.debug("Successfully generated uuid for existing ssh key-pairs");
} catch (SQLException e) {
String errMsg = "Exception while generating uuid for existing ssh key-pairs: " + e.getMessage();
LOG.error(errMsg, e);
throw new CloudRuntimeException(errMsg, e);
}
}
@Override

View File

@ -218,4 +218,9 @@ public class AccountVO implements Account {
public Class<?> getEntityType() {
return Account.class;
}
@Override
public String getName() {
return accountName;
}
}

View File

@ -23,16 +23,24 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.UUID;
@Entity
@Table(name = "ssh_keypairs")
public class SSHKeyPairVO implements SSHKeyPair {
public SSHKeyPairVO() {
uuid = UUID.randomUUID().toString();
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id = null;
@Column(name = "uuid")
private String uuid;
@Column(name = "account_id")
private long accountId;
@ -114,6 +122,14 @@ public class SSHKeyPairVO implements SSHKeyPair {
this.privateKey = privateKey;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
@Override
public Class<?> getEntityType() {
return SSHKeyPair.class;

View File

@ -153,4 +153,9 @@ public class ConsoleProxyVO extends VMInstanceVO implements ConsoleProxy {
public String toString() {
return String.format("Console %s", super.toString());
}
@Override
public String getName() {
return instanceName;
}
}

View File

@ -207,4 +207,8 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter {
}
@Override
public String getName() {
return instanceName;
}
}

View File

@ -133,4 +133,9 @@ public class SecondaryStorageVmVO extends VMInstanceVO implements SecondaryStora
public void setRole(Role role) {
this.role = role;
}
@Override
public String getName() {
return instanceName;
}
}

View File

@ -125,4 +125,9 @@ public class UserVmVO extends VMInstanceVO implements UserVm {
public boolean isUpdateParameters() {
return updateParameters;
}
@Override
public String getName() {
return instanceName;
}
}

View File

@ -553,6 +553,11 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, Vi
return VirtualMachine.class;
}
@Override
public String getName() {
return instanceName;
}
public VirtualMachine.PowerState getPowerState() {
return powerState;
}

View File

@ -236,4 +236,9 @@ public class NicIpAliasVO implements NicIpAlias {
public Class<?> getEntityType() {
return NicIpAlias.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -144,4 +144,9 @@ public class NicSecondaryIpVO implements NicSecondaryIp {
public Class<?> getEntityType() {
return NicSecondaryIp.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -53,6 +53,9 @@ public class AnnotationVO implements Annotation {
@Column(name = "user_uuid")
private String userUuid;
@Column(name = "admins_only")
private boolean adminsOnly;
@Column(name = GenericDao.CREATED_COLUMN)
private Date created;
@ -64,19 +67,14 @@ public class AnnotationVO implements Annotation {
this.uuid = UUID.randomUUID().toString();
}
public AnnotationVO(String text, AnnotationService.EntityType type, String uuid) {
public AnnotationVO(String text, AnnotationService.EntityType type, String uuid, boolean adminsOnly) {
this();
setAnnotation(text);
setEntityType(type);
setEntityUuid(uuid);
setAdminsOnly(adminsOnly);
}
public AnnotationVO(String text, String type, String uuid) {
this();
setAnnotation(text);
setEntityType(type);
setEntityUuid(uuid);
}
// access
@Override
@ -151,4 +149,12 @@ public class AnnotationVO implements Annotation {
public void setRemoved(Date removed) {
this.removed = removed;
}
public boolean isAdminsOnly() {
return adminsOnly;
}
public void setAdminsOnly(boolean adminsOnly) {
this.adminsOnly = adminsOnly;
}
}

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.annotation.dao;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.annotation.AnnotationVO;
import com.cloud.utils.db.GenericDao;
@ -25,6 +26,10 @@ import java.util.List;
* @since 4.11
*/
public interface AnnotationDao extends GenericDao<AnnotationVO, Long> {
public List<AnnotationVO> findByEntityType(String entityType);
public List<AnnotationVO> findByEntity(String entityType, String entityUuid);
List<AnnotationVO> listByEntityType(String entityType, String userUuid, boolean isCallerAdmin, String annotationFilter, String callingUserUuid, String keyword);
List<AnnotationVO> listByEntity(String entityType, String entityUuid, String userUuid, boolean isCallerAdmin, String annotationFilter, String callingUserUuid, String keyword);
List<AnnotationVO> listAllAnnotations(String userUuid, RoleType roleType, String annotationFilter, String keyword);
boolean hasAnnotations(String entityUuid, String entityType, boolean isCallerAdmin);
boolean removeByEntityType(String entityType, String entityUuid);
AnnotationVO findOneByEntityId(String entityUuid);
}

View File

@ -16,12 +16,19 @@
// under the License.
package org.apache.cloudstack.annotation.dao;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.annotation.AnnotationService.EntityType;
import org.apache.cloudstack.annotation.AnnotationVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@ -29,31 +36,112 @@ import java.util.List;
*/
@Component
public class AnnotationDaoImpl extends GenericDaoBase<AnnotationVO, Long> implements AnnotationDao {
private final SearchBuilder<AnnotationVO> AnnotationSearchByType;
private final SearchBuilder<AnnotationVO> AnnotationSearchByTypeAndUuid;
private final SearchBuilder<AnnotationVO> AnnotationSearchBuilder;
public AnnotationDaoImpl() {
super();
AnnotationSearchByType = createSearchBuilder();
AnnotationSearchByType.and("entityType", AnnotationSearchByType.entity().getEntityType(), SearchCriteria.Op.EQ);
AnnotationSearchByType.done();
AnnotationSearchByTypeAndUuid = createSearchBuilder();
AnnotationSearchByTypeAndUuid.and("entityType", AnnotationSearchByTypeAndUuid.entity().getEntityType(), SearchCriteria.Op.EQ);
AnnotationSearchByTypeAndUuid.and("entityUuid", AnnotationSearchByTypeAndUuid.entity().getEntityUuid(), SearchCriteria.Op.EQ);
AnnotationSearchByTypeAndUuid.done();
AnnotationSearchBuilder = createSearchBuilder();
AnnotationSearchBuilder.and("entityType", AnnotationSearchBuilder.entity().getEntityType(), SearchCriteria.Op.EQ);
AnnotationSearchBuilder.and("entityUuid", AnnotationSearchBuilder.entity().getEntityUuid(), SearchCriteria.Op.EQ);
AnnotationSearchBuilder.and("userUuid", AnnotationSearchBuilder.entity().getUserUuid(), SearchCriteria.Op.EQ);
AnnotationSearchBuilder.and("adminsOnly", AnnotationSearchBuilder.entity().getUserUuid(), SearchCriteria.Op.EQ);
AnnotationSearchBuilder.and("annotation", AnnotationSearchBuilder.entity().getAnnotation(), SearchCriteria.Op.LIKE);
AnnotationSearchBuilder.and("entityTypeNotIn", AnnotationSearchBuilder.entity().getEntityType(), SearchCriteria.Op.NOTIN);
AnnotationSearchBuilder.done();
}
@Override public List<AnnotationVO> findByEntityType(String entityType) {
SearchCriteria<AnnotationVO> sc = createSearchCriteria();
private List<AnnotationVO> listAnnotationsOrderedByCreatedDate(SearchCriteria<AnnotationVO> sc) {
Filter filter = new Filter(AnnotationVO.class, "created", false, null, null);
return listBy(sc, filter);
}
@Override
public List<AnnotationVO> listByEntityType(String entityType, String userUuid, boolean isCallerAdmin,
String annotationFilter, String callingUserUuid, String keyword) {
SearchCriteria<AnnotationVO> sc = AnnotationSearchBuilder.create();
sc.addAnd("entityType", SearchCriteria.Op.EQ, entityType);
return listBy(sc);
if (StringUtils.isNotBlank(userUuid)) {
sc.addAnd("userUuid", SearchCriteria.Op.EQ, userUuid);
}
if (!isCallerAdmin) {
List<EntityType> adminOnlyTypes = Arrays.asList(EntityType.SERVICE_OFFERING, EntityType.DISK_OFFERING,
EntityType.NETWORK_OFFERING, EntityType.ZONE, EntityType.POD, EntityType.CLUSTER, EntityType.HOST,
EntityType.DOMAIN, EntityType.PRIMARY_STORAGE, EntityType.SECONDARY_STORAGE,
EntityType.VR, EntityType.SYSTEM_VM);
if (StringUtils.isBlank(entityType)) {
sc.setParameters("entityTypeNotIn", EntityType.SERVICE_OFFERING, EntityType.DISK_OFFERING,
EntityType.NETWORK_OFFERING, EntityType.ZONE, EntityType.POD, EntityType.CLUSTER, EntityType.HOST,
EntityType.DOMAIN, EntityType.PRIMARY_STORAGE, EntityType.SECONDARY_STORAGE,
EntityType.VR, EntityType.SYSTEM_VM);
} else if (adminOnlyTypes.contains(EntityType.valueOf(entityType))) {
return new ArrayList<>();
}
sc.addAnd("adminsOnly", SearchCriteria.Op.EQ, false);
}
if (StringUtils.isNotBlank(keyword)) {
sc.setParameters("annotation", "%" + keyword + "%");
}
return listAnnotationsOrderedByCreatedDate(sc);
}
@Override public List<AnnotationVO> findByEntity(String entityType, String entityUuid) {
SearchCriteria<AnnotationVO> sc = createSearchCriteria();
@Override
public List<AnnotationVO> listByEntity(String entityType, String entityUuid, String userUuid, boolean isCallerAdmin,
String annotationFilter, String callingUserUuid, String keyword) {
SearchCriteria<AnnotationVO> sc = AnnotationSearchBuilder.create();
sc.addAnd("entityType", SearchCriteria.Op.EQ, entityType);
sc.addAnd("entityUuid", SearchCriteria.Op.EQ, entityUuid);
return listBy(sc, null);
if (StringUtils.isNotBlank(userUuid)) {
sc.addAnd("userUuid", SearchCriteria.Op.EQ, userUuid);
}
if (StringUtils.isNotBlank(callingUserUuid) && StringUtils.isNotBlank(annotationFilter) &&
annotationFilter.equalsIgnoreCase("self")) {
sc.addAnd("userUuid", SearchCriteria.Op.EQ, callingUserUuid);
}
if (!isCallerAdmin) {
sc.addAnd("adminsOnly", SearchCriteria.Op.EQ, false);
}
if (StringUtils.isNotBlank(keyword)) {
sc.setParameters("annotation", "%" + keyword + "%");
}
return listAnnotationsOrderedByCreatedDate(sc);
}
@Override
public List<AnnotationVO> listAllAnnotations(String userUuid, RoleType roleType, String annotationFilter, String keyword) {
SearchCriteria<AnnotationVO> sc = AnnotationSearchBuilder.create();
if (StringUtils.isNotBlank(keyword)) {
sc.setParameters("annotation", "%" + keyword + "%");
}
if (StringUtils.isNotBlank(userUuid)) {
sc.addAnd("userUuid", SearchCriteria.Op.EQ, userUuid);
}
if (roleType != RoleType.Admin) {
sc.addAnd("adminsOnly", SearchCriteria.Op.EQ, false);
List<EntityType> notAllowedTypes = EntityType.getNotAllowedTypesForNonAdmins(roleType);
sc.setParameters("entityTypeNotIn", notAllowedTypes.toArray());
}
return listAnnotationsOrderedByCreatedDate(sc);
}
@Override
public boolean hasAnnotations(String entityUuid, String entityType, boolean isCallerAdmin) {
List<AnnotationVO> annotations = listByEntity(entityType, entityUuid, null,
isCallerAdmin, "all", null, null);
return CollectionUtils.isNotEmpty(annotations);
}
@Override
public boolean removeByEntityType(String entityType, String entityUuid) {
SearchCriteria<AnnotationVO> sc = AnnotationSearchBuilder.create();
sc.addAnd("entityType", SearchCriteria.Op.EQ, entityType);
sc.addAnd("entityUuid", SearchCriteria.Op.EQ, entityUuid);
return remove(sc) > 0;
}
@Override
public AnnotationVO findOneByEntityId(String entityUuid) {
SearchCriteria<AnnotationVO> sc = AnnotationSearchBuilder.create();
sc.addAnd("entityUuid", SearchCriteria.Op.EQ, entityUuid);
return findOneBy(sc);
}
}

View File

@ -187,4 +187,9 @@ public class BackupVO implements Backup {
public Class<?> getEntityType() {
return Backup.class;
}
@Override
public String getName() {
return null;
}
}

View File

@ -559,6 +559,11 @@ public class VMEntityVO implements VirtualMachine, FiniteStateObject<State, Virt
return VirtualMachine.class;
}
@Override
public String getName() {
return instanceName;
}
@Override
public boolean isDisplay() {
return display;

View File

@ -19,3 +19,4 @@
-- Schema upgrade cleanup from 4.15.2.0 to 4.16.0.0
--;
ALTER TABLE `cloud`.`ssh_keypairs` MODIFY COLUMN `uuid` varchar(40) NOT NULL UNIQUE;

View File

@ -697,6 +697,22 @@ CREATE VIEW `cloud`.`host_view` AS
GROUP BY
`host`.`id`;
ALTER TABLE `cloud`.`annotations` ADD COLUMN `admins_only` tinyint(1) unsigned NOT NULL DEFAULT 1;
-- Allow annotations for resource admins, domain admins and users
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 2, 'listAnnotations', 'ALLOW');
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 2, 'addAnnotation', 'ALLOW');
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 2, 'removeAnnotation', 'ALLOW');
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 3, 'listAnnotations', 'ALLOW');
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 3, 'addAnnotation', 'ALLOW');
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 3, 'removeAnnotation', 'ALLOW');
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 4, 'listAnnotations', 'ALLOW');
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 4, 'addAnnotation', 'ALLOW');
INSERT INTO `cloud`.`role_permissions` (uuid, role_id, rule, permission) VALUES (UUID(), 4, 'removeAnnotation', 'ALLOW');
-- Add uuid for ssh keypairs
ALTER TABLE `cloud`.`ssh_keypairs` ADD COLUMN `uuid` varchar(40) AFTER `id`;
-- PR#4699 Drop the procedure `ADD_GUEST_OS_AND_HYPERVISOR_MAPPING` if it already exist.
DROP PROCEDURE IF EXISTS `cloud`.`ADD_GUEST_OS_AND_HYPERVISOR_MAPPING`;
@ -757,3 +773,4 @@ UPDATE cloud.user_vm_deploy_as_is_details SET value='' WHERE value IS NULL;
ALTER TABLE cloud.user_vm_deploy_as_is_details MODIFY value text NOT NULL;
UPDATE cloud.user_vm_details SET value='' WHERE value IS NULL;
ALTER TABLE cloud.user_vm_details MODIFY value varchar(5120) NOT NULL;

View File

@ -26,6 +26,8 @@ import java.util.Map;
import javax.inject.Inject;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -66,6 +68,8 @@ public class PrimaryDataStoreHelper {
protected CapacityDao _capacityDao;
@Inject
protected StoragePoolHostDao storagePoolHostDao;
@Inject
private AnnotationDao annotationDao;
public DataStore createPrimaryDataStore(PrimaryDataStoreParameters params) {
if(params == null)
@ -251,6 +255,7 @@ public class PrimaryDataStoreHelper {
this.dataStoreDao.update(poolVO.getId(), poolVO);
dataStoreDao.remove(poolVO.getId());
dataStoreDao.deletePoolTags(poolVO.getId());
annotationDao.removeByEntityType(AnnotationService.EntityType.PRIMARY_STORAGE.name(), poolVO.getUuid());
deletePoolStats(poolVO.getId());
// Delete op_host_capacity entries
this._capacityDao.removeBy(Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED, null, null, null, poolVO.getId());

View File

@ -30,6 +30,8 @@ import javax.inject.Inject;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
@ -189,6 +191,8 @@ public class VolumeServiceImpl implements VolumeService {
private VolumeOrchestrationService _volumeMgr;
@Inject
private StorageManager _storageMgr;
@Inject
private AnnotationDao annotationDao;
private final static String SNAPSHOT_ID = "SNAPSHOT_ID";
@ -1540,6 +1544,7 @@ public class VolumeServiceImpl implements VolumeService {
VolumeInfo vol = volFactory.getVolume(volumeId);
vol.stateTransit(Volume.Event.DestroyRequested);
snapshotMgr.deletePoliciesForVolume(volumeId);
annotationDao.removeByEntityType(AnnotationService.EntityType.VOLUME.name(), vol.getUuid());
vol.stateTransit(Volume.Event.OperationSucceeded);

View File

@ -0,0 +1,48 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.kubernetes.cluster;
import com.cloud.kubernetes.cluster.dao.KubernetesClusterDao;
import com.cloud.utils.component.AdapterBase;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
@Component
public class KubernetesClusterHelperImpl extends AdapterBase implements KubernetesClusterHelper, Configurable {
@Inject
private KubernetesClusterDao kubernetesClusterDao;
@Override
public ControlledEntity findByUuid(String uuid) {
return kubernetesClusterDao.findByUuid(uuid);
}
@Override
public String getConfigComponentName() {
return KubernetesClusterHelper.class.getSimpleName();
}
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[]{};
}
}

View File

@ -39,6 +39,8 @@ import javax.naming.ConfigurationException;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
@ -233,6 +235,8 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
protected ResourceManager resourceManager;
@Inject
protected FirewallRulesDao firewallRulesDao;
@Inject
private AnnotationDao annotationDao;
private void logMessage(final Level logLevel, final String message, final Exception e) {
if (logLevel == Level.WARN) {
@ -648,6 +652,8 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
}
}
}
response.setHasAnnotation(annotationDao.hasAnnotations(kubernetesCluster.getUuid(),
AnnotationService.EntityType.KUBERNETES_CLUSTER.name(), accountService.isRootAdmin(caller.getId())));
response.setVirtualMachines(vmResponses);
return response;
}

View File

@ -22,6 +22,8 @@ import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Level;
@ -55,6 +57,8 @@ public class KubernetesClusterDestroyWorker extends KubernetesClusterResourceMod
@Inject
protected AccountManager accountManager;
@Inject
private AnnotationDao annotationDao;
private List<KubernetesClusterVmMapVO> clusterVMs;
@ -262,6 +266,7 @@ public class KubernetesClusterDestroyWorker extends KubernetesClusterResourceMod
throw new CloudRuntimeException(msg);
}
stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.OperationSucceeded);
annotationDao.removeByEntityType(AnnotationService.EntityType.KUBERNETES_CLUSTER.name(), kubernetesCluster.getUuid());
boolean deleted = kubernetesClusterDao.remove(kubernetesCluster.getId());
if (!deleted) {
logMessage(Level.WARN, String.format("Failed to delete Kubernetes cluster : %s", kubernetesCluster.getName()), null);

View File

@ -19,7 +19,7 @@ package org.apache.cloudstack.api.response;
import java.util.List;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.kubernetes.cluster.KubernetesCluster;
@ -28,7 +28,7 @@ import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
@EntityReference(value = {KubernetesCluster.class})
public class KubernetesClusterResponse extends BaseResponse implements ControlledEntityResponse {
public class KubernetesClusterResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the id of the Kubernetes cluster")
private String id;

View File

@ -15,4 +15,4 @@
# specific language governing permissions and limitations
# under the License.
name=kubernetes-service
parent=compute
parent=kubernetes

View File

@ -34,4 +34,8 @@
<bean id="kubernetesClusterVmMapDaoImpl" class="com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDaoImpl" />
<bean id="kubernetesClusterManagerImpl" class="com.cloud.kubernetes.cluster.KubernetesClusterManagerImpl" />
<bean id="kubernetesClusterHelper" class="com.cloud.kubernetes.cluster.KubernetesClusterHelperImpl" >
<property name="name" value="KubernetesClusterHelper" />
</bean>
</beans>

View File

@ -171,6 +171,7 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate volume metrics response");
}
metricsResponse.setHasAnnotation(volumeResponse.hasAnnotation());
metricsResponse.setDiskSizeGB(volumeResponse.getSize());
metricsResponse.setDiskIopsTotal(volumeResponse.getDiskIORead(), volumeResponse.getDiskIOWrite());
Account account = CallContext.current().getCallingAccount();
@ -194,6 +195,7 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate vm metrics response");
}
metricsResponse.setHasAnnotation(vmResponse.hasAnnotation());
metricsResponse.setIpAddress(vmResponse.getNics());
metricsResponse.setCpuTotal(vmResponse.getCpuNumber(), vmResponse.getCpuSpeed());
metricsResponse.setMemTotal(vmResponse.getMemory());
@ -228,6 +230,7 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
final Double storageThreshold = AlertManager.StorageCapacityThreshold.valueIn(poolClusterId);
final Double storageDisableThreshold = CapacityManager.StorageCapacityDisableThreshold.valueIn(poolClusterId);
metricsResponse.setHasAnnotation(poolResponse.hasAnnotation());
metricsResponse.setDiskSizeUsedGB(poolResponse.getDiskSizeUsed());
metricsResponse.setDiskSizeTotalGB(poolResponse.getDiskSizeTotal(), poolResponse.getOverProvisionFactor());
metricsResponse.setDiskSizeAllocatedGB(poolResponse.getDiskSizeAllocated());
@ -301,6 +304,7 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
metricsResponse.setMemoryAllocatedThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryThreshold);
metricsResponse.setMemoryAllocatedDisableThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryDisableThreshold);
metricsResponses.add(metricsResponse);
metricsResponse.setHasAnnotation(hostResponse.hasAnnotation());
}
return metricsResponses;
}
@ -380,6 +384,7 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
metricsResponse.setMemoryAllocatedThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryThreshold);
metricsResponse.setMemoryAllocatedDisableThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryDisableThreshold);
metricsResponse.setHasAnnotation(clusterResponse.hasAnnotation());
metricsResponses.add(metricsResponse);
}
return metricsResponses;
@ -432,6 +437,7 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
}
}
metricsResponse.setHasAnnotation(zoneResponse.hasAnnotation());
metricsResponse.setState(zoneResponse.getAllocationState());
metricsResponse.setResource(metrics.getUpResources(), metrics.getTotalResources());
// CPU

View File

@ -37,6 +37,8 @@ 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.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants.DomainDetails;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
@ -405,6 +407,8 @@ public class ApiResponseHelper implements ResponseGenerator {
@Inject
private GuestOSDao _guestOsDao;
@Inject
private AnnotationDao annotationDao;
@Inject
private UserStatisticsDao userStatsDao;
@Override
@ -592,6 +596,8 @@ public class ApiResponseHelper implements ResponseGenerator {
CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
}
snapshotResponse.setTags(new HashSet<>(tagResponses));
snapshotResponse.setHasAnnotation(annotationDao.hasAnnotations(snapshot.getUuid(), AnnotationService.EntityType.SNAPSHOT.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
snapshotResponse.setObjectName("snapshot");
return snapshotResponse;
@ -674,6 +680,8 @@ public class ApiResponseHelper implements ResponseGenerator {
CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
}
vmSnapshotResponse.setTags(new HashSet<>(tagResponses));
vmSnapshotResponse.setHasAnnotation(annotationDao.hasAnnotations(vmSnapshot.getUuid(), AnnotationService.EntityType.VM_SNAPSHOT.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
vmSnapshotResponse.setCurrent(vmSnapshot.getCurrent());
vmSnapshotResponse.setType(vmSnapshot.getType().toString());
@ -958,6 +966,8 @@ public class ApiResponseHelper implements ResponseGenerator {
CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
}
ipResponse.setTags(tagResponses);
ipResponse.setHasAnnotation(annotationDao.hasAnnotations(ipAddr.getUuid(), AnnotationService.EntityType.PUBLIC_IP_ADDRESS.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
ipResponse.setObjectName("ipaddress");
return ipResponse;
@ -1134,6 +1144,8 @@ public class ApiResponseHelper implements ResponseGenerator {
capacityResponses.addAll(getStatsCapacityresponse(null, null, pod.getId(), pod.getDataCenterId()));
podResponse.setCapacitites(new ArrayList<CapacityResponse>(capacityResponses));
}
podResponse.setHasAnnotation(annotationDao.hasAnnotations(pod.getUuid(), AnnotationService.EntityType.POD.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
podResponse.setObjectName("pod");
return podResponse;
}
@ -1290,6 +1302,8 @@ public class ApiResponseHelper implements ResponseGenerator {
capacityResponses.addAll(getStatsCapacityresponse(null, cluster.getId(), pod.getId(), pod.getDataCenterId()));
clusterResponse.setCapacitites(new ArrayList<CapacityResponse>(capacityResponses));
}
clusterResponse.setHasAnnotation(annotationDao.hasAnnotations(cluster.getUuid(), AnnotationService.EntityType.CLUSTER.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
clusterResponse.setObjectName("cluster");
return clusterResponse;
}
@ -1493,6 +1507,8 @@ public class ApiResponseHelper implements ResponseGenerator {
vmResponse.setDns2(zone.getDns2());
}
vmResponse.setHasAnnotation(annotationDao.hasAnnotations(vm.getUuid(), AnnotationService.EntityType.SYSTEM_VM.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
List<NicProfile> nicProfiles = ApiDBUtils.getNics(vm);
for (NicProfile singleNicProfile : nicProfiles) {
Network network = ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId());
@ -2125,6 +2141,8 @@ public class ApiResponseHelper implements ResponseGenerator {
if (details != null && !details.isEmpty()) {
response.setDetails(details);
}
response.setHasAnnotation(annotationDao.hasAnnotations(offering.getUuid(), AnnotationService.EntityType.NETWORK_OFFERING.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
return response;
}
@ -2336,6 +2354,8 @@ public class ApiResponseHelper implements ResponseGenerator {
CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
}
response.setTags(tagResponses);
response.setHasAnnotation(annotationDao.hasAnnotations(network.getUuid(), AnnotationService.EntityType.NETWORK.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
if (network.getNetworkACLId() != null) {
NetworkACL acl = ApiDBUtils.findByNetworkACLId(network.getNetworkACLId());
@ -3047,6 +3067,8 @@ public class ApiResponseHelper implements ResponseGenerator {
CollectionUtils.addIgnoreNull(tagResponses, tagResponse);
}
response.setTags(tagResponses);
response.setHasAnnotation(annotationDao.hasAnnotations(vpc.getUuid(), AnnotationService.EntityType.VPC.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
response.setObjectName("vpc");
return response;
}
@ -3282,6 +3304,8 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setIkeVersion(result.getIkeVersion());
response.setSplitConnections(result.getSplitConnections());
response.setObjectName("vpncustomergateway");
response.setHasAnnotation(annotationDao.hasAnnotations(result.getUuid(), AnnotationService.EntityType.VPN_CUSTOMER_GATEWAY.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
populateAccount(response, result.getAccountId());
populateDomain(response, result.getDomainId());
@ -4352,15 +4376,18 @@ public class ApiResponseHelper implements ResponseGenerator {
@Override
public SSHKeyPairResponse createSSHKeyPairResponse(SSHKeyPair sshkeyPair, boolean privatekey) {
SSHKeyPairResponse response = new SSHKeyPairResponse(sshkeyPair.getName(), sshkeyPair.getFingerprint());
SSHKeyPairResponse response = new SSHKeyPairResponse(sshkeyPair.getUuid(), sshkeyPair.getName(), sshkeyPair.getFingerprint());
if (privatekey) {
response = new CreateSSHKeyPairResponse(sshkeyPair.getName(), sshkeyPair.getFingerprint(), sshkeyPair.getPrivateKey());
response = new CreateSSHKeyPairResponse(sshkeyPair.getUuid(), sshkeyPair.getName(),
sshkeyPair.getFingerprint(), sshkeyPair.getPrivateKey());
}
Account account = ApiDBUtils.findAccountById(sshkeyPair.getAccountId());
response.setAccountName(account.getAccountName());
Domain domain = ApiDBUtils.findDomainById(sshkeyPair.getDomainId());
response.setDomainId(domain.getUuid());
response.setDomainName(domain.getName());
response.setHasAnnotation(annotationDao.hasAnnotations(sshkeyPair.getUuid(), AnnotationService.EntityType.SSH_KEYPAIR.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
return response;
}

View File

@ -20,6 +20,9 @@ import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -45,6 +48,8 @@ public class DataCenterJoinDaoImpl extends GenericDaoBase<DataCenterJoinVO, Long
private SearchBuilder<DataCenterJoinVO> dofIdSearch;
@Inject
public AccountManager _accountMgr;
@Inject
private AnnotationDao annotationDao;
protected DataCenterJoinDaoImpl() {
@ -103,6 +108,8 @@ public class DataCenterJoinDaoImpl extends GenericDaoBase<DataCenterJoinVO, Long
}
zoneResponse.setResourceDetails(ApiDBUtils.getResourceDetails(dataCenter.getId(), ResourceObjectType.Zone));
zoneResponse.setHasAnnotation(annotationDao.hasAnnotations(dataCenter.getUuid(), AnnotationService.EntityType.ZONE.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
zoneResponse.setObjectName("zone");
return zoneResponse;

View File

@ -23,8 +23,12 @@ import com.cloud.api.ApiDBUtils;
import com.cloud.dc.VsphereStoragePolicyVO;
import com.cloud.dc.dao.VsphereStoragePolicyDao;
import com.cloud.server.ResourceTag;
import com.cloud.user.AccountManager;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -44,6 +48,10 @@ public class DiskOfferingJoinDaoImpl extends GenericDaoBase<DiskOfferingJoinVO,
@Inject
VsphereStoragePolicyDao _vsphereStoragePolicyDao;
@Inject
private AnnotationDao annotationDao;
@Inject
private AccountManager accountManager;
private final SearchBuilder<DiskOfferingJoinVO> dofIdSearch;
private final Attribute _typeAttr;
@ -100,6 +108,9 @@ public class DiskOfferingJoinDaoImpl extends GenericDaoBase<DiskOfferingJoinVO,
diskOfferingResponse.setZoneId(offering.getZoneUuid());
diskOfferingResponse.setZone(offering.getZoneName());
diskOfferingResponse.setHasAnnotation(annotationDao.hasAnnotations(offering.getUuid(), AnnotationService.EntityType.DISK_OFFERING.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
diskOfferingResponse.setTags(offering.getTags());
diskOfferingResponse.setCustomized(offering.isCustomized());
diskOfferingResponse.setCustomizedIops(offering.isCustomizedIops());

View File

@ -20,10 +20,14 @@ import java.util.EnumSet;
import java.util.List;
import com.cloud.user.AccountManager;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants.DomainDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ResourceLimitAndCountResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -35,12 +39,19 @@ import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import javax.inject.Inject;
@Component
public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implements DomainJoinDao {
public static final Logger s_logger = Logger.getLogger(DomainJoinDaoImpl.class);
private SearchBuilder<DomainJoinVO> domainIdSearch;
@Inject
private AnnotationDao annotationDao;
@Inject
private AccountManager accountManager;
protected DomainJoinDaoImpl() {
domainIdSearch = createSearchBuilder();
@ -74,6 +85,9 @@ public class DomainJoinDaoImpl extends GenericDaoBase<DomainJoinVO, Long> implem
domainResponse.setCreated(domain.getCreated());
domainResponse.setNetworkDomain(domain.getNetworkDomain());
domainResponse.setHasAnnotation(annotationDao.hasAnnotations(domain.getUuid(), AnnotationService.EntityType.DOMAIN.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
if (details.contains(DomainDetails.all) || details.contains(DomainDetails.resource)) {
boolean fullView = (view == ResponseView.Full && domain.getId() == Domain.ROOT_DOMAIN);
setResourceLimits(domain, fullView, domainResponse);

View File

@ -21,6 +21,9 @@ import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -52,6 +55,8 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
private ConfigurationDao _configDao;
@Inject
public AccountManager _accountMgr;
@Inject
private AnnotationDao annotationDao;
private final SearchBuilder<DomainRouterJoinVO> vrSearch;
@ -97,6 +102,9 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
routerResponse.setRequiresUpgrade(true);
}
routerResponse.setHasAnnotation(annotationDao.hasAnnotations(router.getUuid(), AnnotationService.EntityType.VR.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
if (caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN
|| _accountMgr.isRootAdmin(caller.getId())) {
if (router.getHostId() != null) {

View File

@ -27,11 +27,15 @@ import java.util.Set;
import javax.inject.Inject;
import com.cloud.user.AccountManager;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.response.GpuResponse;
import org.apache.cloudstack.api.response.HostForMigrationResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.VgpuResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.ha.HAResource;
import org.apache.cloudstack.ha.dao.HAConfigDao;
@ -69,6 +73,10 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements
private OutOfBandManagementDao outOfBandManagementDao;
@Inject
private ManagementServerHostDao managementServerHostDao;
@Inject
private AnnotationDao annotationDao;
@Inject
private AccountManager accountManager;
private final SearchBuilder<HostJoinVO> hostSearch;
@ -266,6 +274,8 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements
hostResponse.setJobId(host.getJobUuid());
hostResponse.setJobStatus(host.getJobStatus());
}
hostResponse.setHasAnnotation(annotationDao.hasAnnotations(host.getUuid(), AnnotationService.EntityType.HOST.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
hostResponse.setAnnotation(host.getAnnotation());
hostResponse.setLastAnnotated(host.getLastAnnotated ());
hostResponse.setUsername(host.getUsername());

View File

@ -23,6 +23,10 @@ import javax.inject.Inject;
import com.cloud.api.ApiDBUtils;
import com.cloud.storage.StorageStats;
import com.cloud.user.AccountManager;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -42,6 +46,10 @@ public class ImageStoreJoinDaoImpl extends GenericDaoBase<ImageStoreJoinVO, Long
@Inject
private ConfigurationDao _configDao;
@Inject
private AnnotationDao annotationDao;
@Inject
private AccountManager accountManager;
private final SearchBuilder<ImageStoreJoinVO> dsSearch;
@ -83,6 +91,8 @@ public class ImageStoreJoinDaoImpl extends GenericDaoBase<ImageStoreJoinVO, Long
osResponse.setDiskSizeTotal(secStorageStats.getCapacityBytes());
osResponse.setDiskSizeUsed(secStorageStats.getByteUsed());
}
osResponse.setHasAnnotation(annotationDao.hasAnnotations(ids.getUuid(), AnnotationService.EntityType.SECONDARY_STORAGE.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
osResponse.setObjectName("imagestore");
return osResponse;
@ -90,6 +100,10 @@ public class ImageStoreJoinDaoImpl extends GenericDaoBase<ImageStoreJoinVO, Long
@Override
public ImageStoreResponse setImageStoreResponse(ImageStoreResponse response, ImageStoreJoinVO ids) {
if (response.hasAnnotation() == null) {
response.setHasAnnotation(annotationDao.hasAnnotations(ids.getUuid(), AnnotationService.EntityType.SECONDARY_STORAGE.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
}
return response;
}

View File

@ -19,6 +19,10 @@ package com.cloud.api.query.dao;
import java.util.List;
import com.cloud.user.AccountManager;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -31,12 +35,19 @@ import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.vm.InstanceGroup;
import javax.inject.Inject;
@Component
public class InstanceGroupJoinDaoImpl extends GenericDaoBase<InstanceGroupJoinVO, Long> implements InstanceGroupJoinDao {
public static final Logger s_logger = Logger.getLogger(InstanceGroupJoinDaoImpl.class);
private SearchBuilder<InstanceGroupJoinVO> vrIdSearch;
@Inject
private AnnotationDao annotationDao;
@Inject
private AccountManager accountManager;
protected InstanceGroupJoinDaoImpl() {
vrIdSearch = createSearchBuilder();
@ -52,6 +63,8 @@ public class InstanceGroupJoinDaoImpl extends GenericDaoBase<InstanceGroupJoinVO
groupResponse.setId(group.getUuid());
groupResponse.setName(group.getName());
groupResponse.setCreated(group.getCreated());
groupResponse.setHasAnnotation(annotationDao.hasAnnotations(group.getUuid(), AnnotationService.EntityType.INSTANCE_GROUP.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
ApiResponseHelper.populateOwner(groupResponse, group);

View File

@ -21,8 +21,12 @@ import java.util.Map;
import com.cloud.dc.VsphereStoragePolicyVO;
import com.cloud.dc.dao.VsphereStoragePolicyDao;
import com.cloud.user.AccountManager;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -42,6 +46,10 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
@Inject
VsphereStoragePolicyDao _vsphereStoragePolicyDao;
@Inject
private AnnotationDao annotationDao;
@Inject
private AccountManager accountManager;
private SearchBuilder<ServiceOfferingJoinVO> sofIdSearch;
@ -134,6 +142,9 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase<ServiceOfferingJo
long rootDiskSizeInGb = (long) offering.getRootDiskSize() / GB_TO_BYTES;
offeringResponse.setRootDiskSize(rootDiskSizeInGb);
offeringResponse.setHasAnnotation(annotationDao.hasAnnotations(offering.getUuid(), AnnotationService.EntityType.SERVICE_OFFERING.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
return offeringResponse;
}

View File

@ -23,11 +23,15 @@ import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Storage;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StorageStats;
import com.cloud.user.AccountManager;
import com.cloud.utils.StringUtils;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
@ -55,6 +59,10 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO, Lo
@Inject
protected PrimaryDataStoreDao storagePoolDao;
@Inject
private AnnotationDao annotationDao;
@Inject
private AccountManager accountManager;
@Inject
private StoragePoolDetailsDao storagePoolDetailsDao;
@ -144,6 +152,8 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO, Lo
poolResponse.setJobId(pool.getJobUuid());
poolResponse.setJobStatus(pool.getJobStatus());
}
poolResponse.setHasAnnotation(annotationDao.hasAnnotations(pool.getUuid(), AnnotationService.EntityType.PRIMARY_STORAGE.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
poolResponse.setObjectName("storagepool");
return poolResponse;
@ -159,6 +169,10 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO, Lo
response.setTags(tag);
}
}
if (response.hasAnnotation() == null) {
response.setHasAnnotation(annotationDao.hasAnnotations(sp.getUuid(), AnnotationService.EntityType.PRIMARY_STORAGE.name(),
accountManager.isRootAdmin(CallContext.current().getCallingAccount().getId())));
}
return response;
}

View File

@ -26,7 +26,17 @@ import java.util.Set;
import javax.inject.Inject;
import com.cloud.deployasis.DeployAsIsConstants;
import com.cloud.deployasis.TemplateDeployAsIsDetailVO;
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.response.ChildTemplateResponse;
import org.apache.cloudstack.api.response.TemplateResponse;
@ -36,20 +46,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.ApiResponseHelper;
import com.cloud.api.query.vo.ResourceTagJoinVO;
import com.cloud.api.query.vo.TemplateJoinVO;
import com.cloud.deployasis.DeployAsIsConstants;
import com.cloud.deployasis.TemplateDeployAsIsDetailVO;
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.TemplateType;
@ -85,6 +88,8 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
private VMTemplateDetailsDao _templateDetailsDao;
@Inject
private TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
@Inject
private AnnotationDao annotationDao;
private final SearchBuilder<TemplateJoinVO> tmpltIdPairSearch;
@ -262,6 +267,9 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
addTagInformation(template, templateResponse);
}
templateResponse.setHasAnnotation(annotationDao.hasAnnotations(template.getUuid(), AnnotationService.EntityType.TEMPLATE.name(),
_accountService.isRootAdmin(CallContext.current().getCallingAccount().getId())));
templateResponse.setDirectDownload(template.isDirectDownload());
templateResponse.setDeployAsIs(template.isDeployAsIs());
templateResponse.setRequiresHvm(template.isRequiresHvm());
@ -359,6 +367,11 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
addTagInformation(template, templateResponse);
}
if (templateResponse.hasAnnotation() == null) {
templateResponse.setHasAnnotation(annotationDao.hasAnnotations(template.getUuid(), AnnotationService.EntityType.TEMPLATE.name(),
_accountService.isRootAdmin(CallContext.current().getCallingAccount().getId())));
}
return templateResponse;
}
@ -446,6 +459,8 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
isoResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
}
}
isoResponse.setHasAnnotation(annotationDao.hasAnnotations(iso.getUuid(), AnnotationService.EntityType.ISO.name(),
_accountService.isRootAdmin(CallContext.current().getCallingAccount().getId())));
isoResponse.setDirectDownload(iso.isDirectDownload());

View File

@ -29,6 +29,8 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
@ -37,6 +39,7 @@ import org.apache.cloudstack.api.response.NicResponse;
import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.query.QueryService;
import org.apache.log4j.Logger;
@ -82,6 +85,8 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
@Inject
private NicExtraDhcpOptionDao _nicExtraDhcpOptionDao;
@Inject
private AnnotationDao annotationDao;
@Inject
UserStatisticsDao userStatsDao;
private final SearchBuilder<UserVmJoinVO> VmDetailSearch;
@ -312,6 +317,9 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
addTagInformation(userVm, userVmResponse);
}
userVmResponse.setHasAnnotation(annotationDao.hasAnnotations(userVm.getUuid(),
AnnotationService.EntityType.VM.name(), _accountMgr.isRootAdmin(caller.getId())));
if (details.contains(VMDetails.all) || details.contains(VMDetails.affgrp)) {
Long affinityGroupId = userVm.getAffinityGroupId();
if (affinityGroupId != null && affinityGroupId.longValue() != 0) {
@ -489,6 +497,11 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
addTagInformation(uvo, userVmData);
}
if (userVmData.hasAnnotation() == null) {
userVmData.setHasAnnotation(annotationDao.hasAnnotations(uvo.getUuid(),
AnnotationService.EntityType.VM.name(), _accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
}
Long affinityGroupId = uvo.getAffinityGroupId();
if (affinityGroupId != null && affinityGroupId.longValue() != 0) {
AffinityGroupResponse resp = new AffinityGroupResponse();

View File

@ -21,8 +21,11 @@ import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
@ -54,6 +57,8 @@ public class VolumeJoinDaoImpl extends GenericDaoBaseWithTagInformation<VolumeJo
private VmDiskStatisticsDao vmDiskStatsDao;
@Inject
private PrimaryDataStoreDao primaryDataStoreDao;
@Inject
private AnnotationDao annotationDao;
private final SearchBuilder<VolumeJoinVO> volSearch;
@ -236,6 +241,9 @@ public class VolumeJoinDaoImpl extends GenericDaoBaseWithTagInformation<VolumeJo
addTagInformation(volume, volResponse);
}
volResponse.setHasAnnotation(annotationDao.hasAnnotations(volume.getUuid(), AnnotationService.EntityType.VOLUME.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
volResponse.setExtractable(isExtractable);
volResponse.setDisplayVolume(volume.isDisplayVolume());
volResponse.setChainInfo(volume.getChainInfo());
@ -264,6 +272,10 @@ public class VolumeJoinDaoImpl extends GenericDaoBaseWithTagInformation<VolumeJo
if (tag_id > 0) {
addTagInformation(vol, volData);
}
if (volData.hasAnnotation() == null) {
volData.setHasAnnotation(annotationDao.hasAnnotations(vol.getUuid(), AnnotationService.EntityType.VOLUME.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
}
return volData;
}

View File

@ -207,6 +207,11 @@ public class AsyncJobJoinVO extends BaseViewVO implements ControlledViewEntity {
return AsyncJob.class;
}
@Override
public String getName() {
return null;
}
@Override
public String getProjectUuid() {
// TODO Auto-generated method stub

Some files were not shown because too many files have changed in this diff Show More