diff --git a/api/src/main/java/org/apache/cloudstack/annotation/AnnotationService.java b/api/src/main/java/org/apache/cloudstack/annotation/AnnotationService.java index c72fba22ba1..9628bd6475e 100644 --- a/api/src/main/java/org/apache/cloudstack/annotation/AnnotationService.java +++ b/api/src/main/java/org/apache/cloudstack/annotation/AnnotationService.java @@ -45,7 +45,7 @@ public interface AnnotationService { 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), - AUTOSCALE_VM_GROUP(true); + AUTOSCALE_VM_GROUP(true), MANAGEMENT_SERVER(false),; private final boolean usersAllowed; diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java b/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java index 0a7ece7b7d8..9267ca6fa96 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java @@ -77,7 +77,8 @@ public enum ApiCommandResourceType { Pod(com.cloud.dc.Pod.class), VmSnapshot(com.cloud.vm.snapshot.VMSnapshot.class), Role(org.apache.cloudstack.acl.Role.class), - VpnCustomerGateway(com.cloud.network.Site2SiteCustomerGateway.class); + VpnCustomerGateway(com.cloud.network.Site2SiteCustomerGateway.class), + ManagementServer(org.apache.cloudstack.management.ManagementServerHost.class); private final Class clazz; diff --git a/api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java b/api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java index 834291ef21c..54a53f39578 100644 --- a/api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java +++ b/api/src/main/java/org/apache/cloudstack/management/ManagementServerHost.java @@ -16,10 +16,11 @@ // under the License. package org.apache.cloudstack.management; +import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; -public interface ManagementServerHost extends InternalIdentity, Identity { +public interface ManagementServerHost extends InternalIdentity, Identity, ControlledEntity { enum State { Up, Down, PreparingToShutDown, ReadyToShutDown, ShuttingDown } diff --git a/framework/cluster/src/main/java/com/cloud/cluster/ManagementServerHostVO.java b/framework/cluster/src/main/java/com/cloud/cluster/ManagementServerHostVO.java index 121b939c598..2918ccd22d7 100644 --- a/framework/cluster/src/main/java/com/cloud/cluster/ManagementServerHostVO.java +++ b/framework/cluster/src/main/java/com/cloud/cluster/ManagementServerHostVO.java @@ -124,6 +124,11 @@ public class ManagementServerHostVO implements ManagementServerHost { this.msid = msid; } + @Override + public Class getEntityType() { + return ManagementServerHost.class; + } + @Override public String getName() { return name; @@ -196,4 +201,14 @@ public class ManagementServerHostVO implements ManagementServerHost { public String toString() { return new StringBuilder("ManagementServer[").append("-").append(id).append("-").append(msid).append("-").append(state).append("]").toString(); } + + @Override + public long getDomainId() { + return 1L; + } + + @Override + public long getAccountId() { + return 1L; + } } diff --git a/server/src/main/java/org/apache/cloudstack/annotation/AnnotationManagerImpl.java b/server/src/main/java/org/apache/cloudstack/annotation/AnnotationManagerImpl.java index cc5984699e8..59879791ba3 100644 --- a/server/src/main/java/org/apache/cloudstack/annotation/AnnotationManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/annotation/AnnotationManagerImpl.java @@ -26,6 +26,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.cluster.ManagementServerHostVO; import com.cloud.user.dao.UserDataDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.Role; @@ -50,6 +51,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; +import com.cloud.cluster.dao.ManagementServerHostDao; import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -158,6 +160,8 @@ public final class AnnotationManagerImpl extends ManagerBase implements Annotati @Inject private UserDataDao userDataDao; @Inject + private ManagementServerHostDao managementServerHostDao; + @Inject EntityManager entityManager; private static final List adminRoles = Collections.singletonList(RoleType.Admin); @@ -192,6 +196,7 @@ public final class AnnotationManagerImpl extends ManagerBase implements Annotati s_typeMap.put(EntityType.VR, ApiCommandResourceType.DomainRouter); s_typeMap.put(EntityType.SYSTEM_VM, ApiCommandResourceType.SystemVm); s_typeMap.put(EntityType.AUTOSCALE_VM_GROUP, ApiCommandResourceType.AutoScaleVmGroup); + s_typeMap.put(EntityType.MANAGEMENT_SERVER, ApiCommandResourceType.Host); } public List getKubernetesClusterHelpers() { @@ -532,6 +537,8 @@ public final class AnnotationManagerImpl extends ManagerBase implements Annotati return kubernetesClusterHelpers.get(0).findByUuid(entityUuid); case AUTOSCALE_VM_GROUP: return autoScaleVmGroupDao.findByUuid(entityUuid); + case MANAGEMENT_SERVER: + return managementServerHostDao.findByUuid(entityUuid); default: throw new CloudRuntimeException("Invalid entity type " + type); } @@ -607,6 +614,9 @@ public final class AnnotationManagerImpl extends ManagerBase implements Annotati case SYSTEM_VM: VMInstanceVO instance = vmInstanceDao.findByUuid(entityUuid); return instance != null ? instance.getInstanceName() : null; + case MANAGEMENT_SERVER: + ManagementServerHostVO mgmtServer = managementServerHostDao.findByUuid(entityUuid); + return mgmtServer != null ? mgmtServer.getName() : null; default: return null; } diff --git a/test/integration/smoke/test_annotations.py b/test/integration/smoke/test_annotations.py index 812b3dcb4d7..e527b96aa5c 100644 --- a/test/integration/smoke/test_annotations.py +++ b/test/integration/smoke/test_annotations.py @@ -83,6 +83,7 @@ class TestAnnotations(cloudstackTestCase): cls.host = list_hosts(cls.apiclient, zoneid=cls.zone.id, type='Routing')[0] + cls.mgmt_server = list_mgmt_servers(cls.apiclient)[0] @classmethod def tearDownClass(cls): @@ -135,6 +136,12 @@ class TestAnnotations(cloudstackTestCase): self.addAnnotation("annotation1", self.host.id, "HOST") self.assertEqual(self.added_annotations[-1].annotation.annotation, "annotation1") + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_01_add_ms_annotation(self): + """Testing the addAnnotations API ability to add an annoatation per management server""" + self.addAnnotation("mgmt-server-annotation1", self.mgmt_server.id, "MANAGEMENT_SERVER") + self.assertEqual(self.added_annotations[-1].annotation.annotation, "mgmt-server-annotation1") + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") def test_02_add_multiple_annotations(self): """Testing the addAnnotations API ability to add an annoatation per host diff --git a/tools/marvin/marvin/lib/common.py b/tools/marvin/marvin/lib/common.py index f1f09bbff96..cc773654faa 100644 --- a/tools/marvin/marvin/lib/common.py +++ b/tools/marvin/marvin/lib/common.py @@ -58,6 +58,7 @@ from marvin.cloudstackAPI import (listConfigurations, listNetworkOfferings, listResourceLimits, listVPCOfferings, + listManagementServers, migrateSystemVm) from marvin.sshClient import SshClient from marvin.codes import (PASS, FAILED, ISOLATED_NETWORK, VPC_NETWORK, @@ -1056,6 +1057,14 @@ def list_vpc_offerings(apiclient, **kwargs): cmd.listall=True return(apiclient.listVPCOfferings(cmd)) +def list_mgmt_servers(apiclient, **kwargs): + """ Lists Management Servers """ + + cmd = listManagementServers.listManagementServersCmd() + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + if 'account' in list(kwargs.keys()) and 'domainid' in list(kwargs.keys()): + cmd.listall=True + return(apiclient.listManagementServers(cmd)) def update_resource_count(apiclient, domainid, accountid=None, projectid=None, rtype=None): diff --git a/ui/src/components/view/AnnotationsTab.vue b/ui/src/components/view/AnnotationsTab.vue index a546d5089f4..97cf926dee3 100644 --- a/ui/src/components/view/AnnotationsTab.vue +++ b/ui/src/components/view/AnnotationsTab.vue @@ -192,6 +192,7 @@ export default { case 'SystemVm': return 'SYSTEM_VM' case 'VirtualRouter': return 'VR' case 'AutoScaleVmGroup': return 'AUTOSCALE_VM_GROUP' + case 'ManagementServer': return 'MANAGEMENT_SERVER' default: return '' } }, diff --git a/ui/src/config/section/infra/managementServers.js b/ui/src/config/section/infra/managementServers.js index e4f9217a00c..14bb5f11788 100644 --- a/ui/src/config/section/infra/managementServers.js +++ b/ui/src/config/section/infra/managementServers.js @@ -24,6 +24,7 @@ export default { icon: 'CloudServerOutlined', docHelp: 'conceptsandterminology/concepts.html#management-server-overview', permission: ['listManagementServersMetrics'], + resourceType: 'ManagementServer', columns: () => { const fields = ['name', 'state', 'version'] const metricsFields = ['collectiontime', 'availableprocessors', 'cpuload', 'heapmemoryused', 'agentcount'] @@ -80,6 +81,9 @@ export default { value: (record, params) => { return record.id } } } + }, { + name: 'comments', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) } ] }