Mshost stats (#5588)

* ms stats thread added

* initial data collection for management server

* empty list management server metrics command

* bean copy into MS metrics object

* ms status VO

* further API and DB plumbing

* minimal metrics response in API

* remove commented, refactor data collection plumbing

* javadocs

* surpress stacktrace on expected error

* update status experiment

* ms status publish framework added

* review comment addressed

* static data to DB and API, /proc/ reading

* addressing review comments

* ui for ms details

* small ui adjustment

* beanCopy

* agentcount response and system parameter

* labels

* package-lock

* add version strings to regular list API

* add shutdown time to DB

* add last start and last stop to regular list response

* distro info in regular response/session  count added

* metrics as details

* add heap used and remove details map

* thread-statusses

* move db upgrade to 4.17

* sysmem

* procmem

* ui demo comments applied

* javadoc

* get conf and log file locations

* loginfo

* cpuLoadStats

* no.remote

* extra spaces removed

* clusterlistener

* add unit to kb value

* revert accidental rename

* silly fqcn removed

* get mem info from bean is possible

* refactor long sequence for readability

* registerListener

* listUsageMetrics and isDbLocal

* rats

* local usage and db or not

* minimal listDbMetrics

* db vars and stats

* cleanup and #queries queried

* db stats calculation

* rat

* remove list response wrapper from sinlge details-lists responses

* rudimentary metrics view

* metrics table cleanup

* table makeup, collection dates

* move component to appropriate location

* capitalisation removed

* rebase error resolved

* rename deamon to daemon

* small style comments applied

* another merge issue

* naming comments and boot time

* stop/start prefixed with server

* layout-fix

* listMSMetrics test and test refactor

* usage metrics test

* db metrics test

* extra validations

* Update ui/public/locales/en.json

Co-authored-by: sureshanaparti <12028987+sureshanaparti@users.noreply.github.com>

* descriptions of loadaverages and replica's

* collection time on top

* cpu load on metrics overview

* DbStatsCollection

* some parameter description texts

* labels adjusted

* new output 'kernelversion' and log info cleanup

* labels

* Update api/src/main/java/com/cloud/server/ManagementServerHostStats.java

Co-authored-by: sureshanaparti <12028987+sureshanaparti@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/response/DbMetricsResponse.java

Co-authored-by: sureshanaparti <12028987+sureshanaparti@users.noreply.github.com>

* Update framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerHostDao.java

Co-authored-by: Rodrigo D. Lopez <19981369+RodrigoDLopez@users.noreply.github.com>

* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java

Co-authored-by: Rodrigo D. Lopez <19981369+RodrigoDLopez@users.noreply.github.com>

* Update api/src/main/java/org/apache/cloudstack/api/response/ManagementServerResponse.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update api/src/main/java/org/apache/cloudstack/api/response/ManagementServerResponse.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update engine/schema/src/main/java/com/cloud/host/dao/HostDao.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update server/src/main/java/com/cloud/server/StatsCollector.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerHostDao.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update server/src/main/java/com/cloud/server/StatsCollector.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update server/src/main/java/com/cloud/server/StatsCollector.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update server/src/main/java/com/cloud/server/StatsCollector.java

Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java

* some (more) refactorring suggestions applied

* human readable memory sizes

* rat

* actual collection time instead of query time, improved descriptions

* merge errors fixed

* optional metric values

* javadoc and logging

* names of jmx vars have changed

* vue3-compatibility

* new output parameter type

* lower retention default

* vue3 fixes

* polish comments

* polish comments 2, the reckoning

* note on usage servers

* merge conflict errors

* pollish

* conditional assertion to deal with simulator restart

Co-authored-by: Daan Hoogland <dahn@onecht.net>
Co-authored-by: sureshanaparti <12028987+sureshanaparti@users.noreply.github.com>
Co-authored-by: Rodrigo D. Lopez <19981369+RodrigoDLopez@users.noreply.github.com>
Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>
Co-authored-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
dahn 2022-04-22 13:48:19 +02:00 committed by GitHub
parent 9a53bada19
commit 545e89c1cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 36410 additions and 617 deletions

View File

@ -0,0 +1,113 @@
//
// 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.server;
import java.util.Date;
/**
* management server related stats
*/
public interface ManagementServerHostStats {
Date getCollectionTime();
Date getSystemBootTime();
long getManagementServerHostId();
String getManagementServerHostUuid();
long getSessions();
double getCpuUtilization();
long getTotalJvmMemoryBytes();
double getFreeJvmMemoryBytes();
long getProcessJvmMemoryBytes();
long getJvmUptime();
long getJvmStartTime();
int getAvailableProcessors();
double getLoadAverage();
long getTotalInit();
long getTotalUsed();
long getMaxJvmMemoryBytes();
long getTotalCommitted();
long getPid();
String getJvmName();
String getJvmVendor();
String getJvmVersion();
String getOsDistribution();
int getAgentCount();
long getHeapMemoryUsed();
long getHeapMemoryTotal();
int getThreadsBlockedCount();
int getThreadsTotalCount();
int getThreadsDaemonCount();
int getThreadsRunnableCount();
int getThreadsTerminatedCount();
int getThreadsWaitingCount();
long getSystemMemoryTotal();
long getSystemMemoryFree();
long getSystemMemoryUsed();
long getSystemMemoryVirtualSize();
String getLogInfo();
/**
* @return in mega hertz
*/
double getSystemTotalCpuCycles();
double[] getSystemLoadAverages();
long[] getSystemCyclesUsage();
boolean isDbLocal();
boolean isUsageLocal();
String getKernelVersion();
}

View File

@ -239,10 +239,17 @@ public class ApiConstants {
public static final String IS_RECURSIVE = "isrecursive";
public static final String ISO_FILTER = "isofilter";
public static final String ISO_GUEST_OS_NONE = "None";
public static final String JAVA_DISTRIBUTION = "javadistribution";
public static final String JAVA_VERSION = "javaversion";
public static final String JOB_ID = "jobid";
public static final String JOB_STATUS = "jobstatus";
public static final String KEEPALIVE_ENABLED = "keepaliveenabled";
public static final String KERNEL_VERSION = "kernelversion";
public static final String LABEL = "label";
public static final String LASTNAME = "lastname";
public static final String LAST_BOOT = "lastboottime";
public static final String LAST_SERVER_START = "lastserverstart";
public static final String LAST_SERVER_STOP = "lastserverstop";
public static final String LEVEL = "level";
public static final String LENGTH = "length";
public static final String LIMIT_CPU_USE = "limitcpuuse";
@ -260,7 +267,6 @@ public class ApiConstants {
public static final String MIGRATION_TYPE = "migrationtype";
public static final String MEMORY = "memory";
public static final String MODE = "mode";
public static final String KEEPALIVE_ENABLED = "keepaliveenabled";
public static final String NAME = "name";
public static final String METHOD_NAME = "methodname";
public static final String NETWORK_DOMAIN = "networkdomain";
@ -273,6 +279,7 @@ public class ApiConstants {
public static final String NEW_END_IP = "newendip";
public static final String NUM_RETRIES = "numretries";
public static final String OFFER_HA = "offerha";
public static final String OS_DISTRIBUTION = "osdistribution";
public static final String IS_SYSTEM_OFFERING = "issystem";
public static final String IS_DEFAULT_USE = "defaultuse";
public static final String OLD_FORMAT = "oldformat";

View File

@ -22,6 +22,9 @@ import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import org.apache.cloudstack.management.ManagementServerHost.State;
import java.util.Date;
@EntityReference(value = ManagementServerHost.class)
public class ManagementServerResponse extends BaseResponse {
@ -35,12 +38,80 @@ public class ManagementServerResponse extends BaseResponse {
@SerializedName(ApiConstants.STATE)
@Param(description = "the state of the management server")
private ManagementServerHost.State state;
private State state;
@SerializedName(ApiConstants.VERSION)
@Param(description = "the version of the management server")
private String version;
@SerializedName(ApiConstants.JAVA_DISTRIBUTION)
@Param(description = "the java distribution name running the management server process")
private String javaDistribution;
@SerializedName(ApiConstants.JAVA_VERSION)
@Param(description = "the version of the java distribution running the management server process")
private String javaVersion;
@SerializedName(ApiConstants.OS_DISTRIBUTION)
@Param(description = "the name of the OS distribution running on the management server")
private String osDistribution;
@SerializedName(ApiConstants.LAST_SERVER_START)
@Param(description = "the last time this Management Server was started")
private Date lastServerStart;
@SerializedName(ApiConstants.LAST_SERVER_STOP)
@Param(description = "the last time this Management Server was stopped")
private Date lastServerStop;
@SerializedName(ApiConstants.LAST_BOOT)
@Param(description = "the last time the host on which this Management Server runs was booted")
private Date lastBoot;
@SerializedName(ApiConstants.KERNEL_VERSION)
@Param(description = "the running OS kernel version for this Management Server")
private String kernelVersion;
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
public State getState() {
return state;
}
public String getVersion() {
return version;
}
public String getJavaVersion() {
return javaVersion;
}
public String getJavaDistribution() {
return javaDistribution;
}
public String getOsDistribution() {
return osDistribution;
}
public Date getLastServerStart() {
return lastServerStart;
}
public Date getLastServerStop() {
return lastServerStop;
}
public Date getLastBoot() {
return lastBoot;
}
public void setId(String id) {
this.id = id;
}
@ -49,11 +120,39 @@ public class ManagementServerResponse extends BaseResponse {
this.name = name;
}
public void setState(ManagementServerHost.State state) {
public void setState(State state) {
this.state = state;
}
public void setVersion(String version) {
this.version = version;
}
public void setJavaDistribution(String javaDistribution) {
this.javaDistribution = javaDistribution;
}
public void setJavaVersion(String javaVersion) {
this.javaVersion = javaVersion;
}
public void setOsDistribution(String osDistribution) {
this.osDistribution = osDistribution;
}
public void setLastServerStart(Date lastServerStart) {
this.lastServerStart = lastServerStart;
}
public void setLastServerStop(Date lastServerStop) {
this.lastServerStop = lastServerStop;
}
public void setLastBoot(Date lastBoot) {
this.lastBoot = lastBoot;
}
public void setKernelVersion(String kernelVersion) {
this.kernelVersion = kernelVersion;
}
}

View File

@ -0,0 +1,45 @@
// 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.management;
import org.apache.cloudstack.api.InternalIdentity;
import java.util.Date;
public interface ManagementServerStatus extends InternalIdentity {
long getId();
String getMsId();
Date getLastJvmStart();
Date getLastJvmStop();
Date getLastSystemBoot();
String getOsDistribution();
String getJavaName();
String getJavaVersion();
Date getUpdated();
Date getCreated();
Date getRemoved();
}

View File

@ -28,6 +28,9 @@
<listener>
<listener-class>org.apache.cloudstack.spring.module.web.CloudStackContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.cloud.api.ApiSessionListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/cloudstack/webApplicationContext.xml</param-value>

View File

@ -26,7 +26,7 @@ import com.cloud.host.Status;
import com.cloud.utils.nio.Link;
/**
* ConnectedAgentAttache implements an direct connection to this management server.
* ConnectedAgentAttache implements a direct connection to this management server.
*/
public class ConnectedAgentAttache extends AgentAttache {
private static final Logger s_logger = Logger.getLogger(ConnectedAgentAttache.class);

View File

@ -142,4 +142,11 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
HostVO findByName(String name);
List<HostVO> listHostsWithActiveVMs(long offeringId);
/**
* Retrieves the number of hosts/agents this {@see ManagementServer} has responsibility over.
* @param msid the id of the {@see ManagementServer}
* @return the number of hosts/agents this {@see ManagementServer} has responsibility over
*/
int countByMs(long msid);
}

View File

@ -119,6 +119,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
protected SearchBuilder<HostVO> UnmanagedApplianceSearch;
protected SearchBuilder<HostVO> MaintenanceCountSearch;
protected SearchBuilder<HostVO> HostTypeCountSearch;
protected SearchBuilder<HostVO> ResponsibleMsCountSearch;
protected SearchBuilder<HostVO> HostTypeZoneCountSearch;
protected SearchBuilder<HostVO> ClusterStatusSearch;
protected SearchBuilder<HostVO> TypeNameZoneSearch;
@ -179,6 +180,10 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
HostTypeCountSearch.and("type", HostTypeCountSearch.entity().getType(), SearchCriteria.Op.EQ);
HostTypeCountSearch.done();
ResponsibleMsCountSearch = createSearchBuilder();
ResponsibleMsCountSearch.and("managementServerId", ResponsibleMsCountSearch.entity().getManagementServerId(), SearchCriteria.Op.EQ);
ResponsibleMsCountSearch.done();
HostTypeZoneCountSearch = createSearchBuilder();
HostTypeZoneCountSearch.and("type", HostTypeZoneCountSearch.entity().getType(), SearchCriteria.Op.EQ);
HostTypeZoneCountSearch.and("dc", HostTypeZoneCountSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
@ -1287,6 +1292,13 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
}
}
@Override
public int countByMs(long msid) {
SearchCriteria<HostVO> sc = ResponsibleMsCountSearch.create();
sc.setParameters("managementServerId", msid);
return getCount(sc);
}
@Override
public List<HostVO> listAllHostsByType(Host.Type type) {
SearchCriteria<HostVO> sc = TypeSearch.create();

View File

@ -118,6 +118,7 @@
<bean id="inlineLoadBalancerNicMapDaoImpl" class="com.cloud.network.dao.InlineLoadBalancerNicMapDaoImpl" />
<bean id="instanceGroupDaoImpl" class="com.cloud.vm.dao.InstanceGroupDaoImpl" />
<bean id="instanceGroupJoinDaoImpl" class="com.cloud.api.query.dao.InstanceGroupJoinDaoImpl" />
<bean id="managementServerJoinDaoImpl" class="com.cloud.api.query.dao.ManagementServerJoinDaoImpl" />
<bean id="instanceGroupVMMapDaoImpl" class="com.cloud.vm.dao.InstanceGroupVMMapDaoImpl" />
<bean id="itWorkDaoImpl" class="com.cloud.vm.ItWorkDaoImpl" />
<bean id="lBHealthCheckPolicyDaoImpl" class="com.cloud.network.dao.LBHealthCheckPolicyDaoImpl" />
@ -128,6 +129,7 @@
<bean id="loadBalancerCertMapDaoImpl" class="com.cloud.network.dao.LoadBalancerCertMapDaoImpl" />
<bean id="managementServerHostDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostDaoImpl" />
<bean id="managementServerHostPeerDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostPeerDaoImpl" />
<bean id="managementServerStatusDaoImpl" class="com.cloud.cluster.dao.ManagementServerStatusDaoImpl" />
<bean id="networkAccountDaoImpl" class="com.cloud.network.dao.NetworkAccountDaoImpl" />
<bean id="networkACLDaoImpl" class="com.cloud.network.vpc.dao.NetworkACLDaoImpl" />
<bean id="networkACLItemDaoImpl" class="com.cloud.network.vpc.dao.NetworkACLItemDaoImpl" />

View File

@ -699,3 +699,85 @@ CREATE VIEW `cloud`.`domain_router_view` AS
`cloud`.`async_job` ON async_job.instance_id = vm_instance.id
and async_job.instance_type = 'DomainRouter'
and async_job.job_status = 0;
INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'listConfigurations', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule;
INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'updateConfiguration', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule;
-- table for network permissions
CREATE TABLE `cloud`.`network_permissions` (
`id` bigint unsigned NOT NULL auto_increment,
`network_id` bigint unsigned NOT NULL,
`account_id` bigint unsigned NOT NULL,
PRIMARY KEY (`id`),
INDEX `i_network_permission_network_id`(`network_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `cloud`.`user_vm_details`(`vm_id`, `name`, `value`)
SELECT `user_vm_details`.`vm_id`, 'SSH.KeyPairNames', `ssh_keypairs`.`keypair_name`
FROM `cloud`.`user_vm_details`
INNER JOIN `cloud`.`ssh_keypairs` ON ssh_keypairs.public_key = user_vm_details.value
INNER JOIN `cloud`.`vm_instance` ON vm_instance.id = user_vm_details.vm_id
WHERE ssh_keypairs.account_id = vm_instance.account_id;
ALTER TABLE `cloud`.`kubernetes_cluster` ADD COLUMN `security_group_id` bigint unsigned DEFAULT NULL,
ADD CONSTRAINT `fk_kubernetes_cluster__security_group_id` FOREIGN KEY `fk_kubernetes_cluster__security_group_id`(`security_group_id`) REFERENCES `security_group`(`id`) ON DELETE CASCADE;
-- PR#5984 Create table to persist VM stats.
DROP TABLE IF EXISTS `cloud`.`vm_stats`;
CREATE TABLE `cloud`.`vm_stats` (
`id` bigint unsigned NOT NULL auto_increment COMMENT 'id',
`vm_id` bigint unsigned NOT NULL,
`mgmt_server_id` bigint unsigned NOT NULL,
`timestamp` datetime NOT NULL,
`vm_stats_data` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- PR#5984 Update name for global configuration vm.stats.increment.metrics
Update configuration set name='vm.stats.increment.metrics' where name='vm.stats.increment.metrics.in.memory';
--
-- Management Server Status
--
ALTER TABLE `cloud`.`mshost` ADD CONSTRAINT `mshost_UUID` UNIQUE KEY (`uuid`);
CREATE TABLE `cloud`.`mshost_status` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`ms_id` varchar(40) DEFAULT NULL COMMENT 'the uuid of the management server record',
`last_jvm_start` datetime DEFAULT NULL COMMENT 'the last start time for this MS',
`last_jvm_stop` datetime DEFAULT NULL COMMENT 'the last stop time for this MS',
`last_system_boot` datetime DEFAULT NULL COMMENT 'the last system boot time for the host of this MS',
`os_distribution` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT 'the name of the os type running on the host of this MS',
`java_name` varchar(64) DEFAULT NULL COMMENT 'the name of the java distribution running this MS',
`java_version` varchar(64) DEFAULT NULL COMMENT 'the version of the java distribution running this MS',
`updated` datetime DEFAULT NULL,
`created` datetime DEFAULT NULL,
`removed` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `uc_ms_id` UNIQUE (`ms_id`),
CONSTRAINT `mshost_status_FK` FOREIGN KEY (`ms_id`) REFERENCES `mshost` (`uuid`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3;
DROP VIEW IF EXISTS `cloud`.`mshost_view`;
CREATE VIEW `cloud`.`mshost_view` AS
select
`cloud`.`mshost`.`id` AS `id`,
`cloud`.`mshost`.`msid` AS `msid`,
`cloud`.`mshost`.`runid` AS `runid`,
`cloud`.`mshost`.`name` AS `name`,
`cloud`.`mshost`.`uuid` AS `uuid`,
`cloud`.`mshost`.`state` AS `state`,
`cloud`.`mshost`.`version` AS `version`,
`cloud`.`mshost`.`service_ip` AS `service_ip`,
`cloud`.`mshost`.`service_port` AS `service_port`,
`cloud`.`mshost`.`last_update` AS `last_update`,
`cloud`.`mshost`.`removed` AS `removed`,
`cloud`.`mshost`.`alert_count` AS `alert_count`,
`cloud`.`mshost_status`.`last_jvm_start` AS `last_jvm_start`,
`cloud`.`mshost_status`.`last_jvm_stop` AS `last_jvm_stop`,
`cloud`.`mshost_status`.`last_system_boot` AS `last_system_boot`,
`cloud`.`mshost_status`.`os_distribution` AS `os_distribution`,
`cloud`.`mshost_status`.`java_name` AS `java_name`,
`cloud`.`mshost_status`.`java_version` AS `java_version`
from
(`cloud`.`mshost`
left join `cloud`.`mshost_status` on
((`cloud`.`mshost`.`uuid` = `cloud`.`mshost_status`.`ms_id`)));

View File

@ -21,6 +21,9 @@ import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.utils.component.Manager;
/**
* The definition of the framework for inter MS communication.
*/
public interface ClusterManager extends Manager {
static final String ALERT_SUBJECT = "cluster-alert";
final ConfigKey<Integer> HeartbeatInterval = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.interval", "management-server", "1500",
@ -28,20 +31,26 @@ public interface ClusterManager extends Manager {
final ConfigKey<Integer> HeartbeatThreshold = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.threshold", "management-server", "150000",
"Threshold before self-fence the management server", true);
/**
* Adds a new packet to the incoming queue.
* @param pdu protocol data unit
*/
void OnReceiveClusterServicePdu(ClusterServicePdu pdu);
void publishStatus(String status);
/**
* This executes
* @param strPeer
* @param agentId
* @param cmds
* @param stopOnError
* @return
* Creates and registers a PDU, notifies listeners, and waits on the PDU to be notified.
* @param strPeer destination
* @param agentId reference to a resource
* @param cmds any json string (probably containing encoded commands)
* @param stopOnError should the other side continue id an error is encountered
* @return json encoded answer from the far side
*/
String execute(String strPeer, long agentId, String cmds, boolean stopOnError);
/**
* Broadcast the command to all of the management server nodes.
* Broadcast the command to all the management server nodes.
* @param agentId agent id this broadcast is regarding
* @param cmds commands to broadcast
*/
@ -53,19 +62,44 @@ public interface ClusterManager extends Manager {
void registerDispatcher(Dispatcher dispatcher);
/**
* Registers a listener for incoming status changes of ManagementServers.
*
* @param administrator the object administrating statuses
*/
void registerStatusAdministrator(StatusAdministrator administrator);
ManagementServerHost getPeer(String peerName);
/**
*
* @return A {code}Long.toString({code}{@see getManagementNodeId()}{code}){code} representation of the PID of the management server process.
*/
String getSelfPeerName();
long getManagementNodeId();
/**
* determined by the time
* @return The start time of the management server as {code}System.currentTimeMillis(){code}.
*/
long getCurrentRunId();
public long getManagementRunId(long msId);
/**
* @return The other MS's id as derived from start time as stored in the db.
*/
long getManagementRunId(long msId);
public interface Dispatcher {
interface Dispatcher {
String getName();
String dispatch(ClusterServicePdu pdu);
}
/**
* The definition of what the client of {@see registerStatusAdministrator()} should implement.
*/
interface StatusAdministrator {
String newStatus(ClusterServicePdu pdu);
}
}

View File

@ -40,6 +40,7 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.cluster.dao.ManagementServerStatusDao;
import org.apache.cloudstack.management.ManagementServerHost;
import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -97,10 +98,14 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
@Inject
private ManagementServerHostDao _mshostDao;
@Inject
private ManagementServerStatusDao mshostStatusDao;
@Inject
private ManagementServerHostPeerDao _mshostPeerDao;
protected Dispatcher _dispatcher;
private StatusAdministrator statusAdministrator;
//
// pay attention to _mshostId and _msid
// _mshostId is the primary key of management host table
@ -139,6 +144,11 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
_dispatcher = dispatcher;
}
@Override
public void registerStatusAdministrator(final StatusAdministrator administrator) {
statusAdministrator = administrator;
}
private ClusterServiceRequestPdu popRequestPdu(final long ackSequenceId) {
synchronized (_outgoingPdusWaitingForAck) {
if (_outgoingPdusWaitingForAck.get(ackSequenceId) != null) {
@ -312,6 +322,12 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
} else {
s_logger.warn("Original request has already been cancelled. pdu: " + pdu.getJsonPackage());
}
} else if (pdu.getPduType() == ClusterServicePdu.PDU_TYPE_STATUS_UPDATE) {
if (statusAdministrator == null) {
s_logger.warn("No status administration to report a status update too.");
} else {
statusAdministrator.newStatus(pdu);
}
} else {
String result = _dispatcher.dispatch(pdu);
if (result == null) {
@ -385,6 +401,37 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
addOutgoingClusterPdu(pdu);
}
@Override
public void publishStatus(final String status) {
final Date cutTime = DateUtil.currentGMTTime();
final List<ManagementServerHostVO> peers = _mshostDao.getActiveList(new Date(cutTime.getTime() - HeartbeatThreshold.value()));
for (final ManagementServerHostVO peer : peers) {
final String peerName = Long.toString(peer.getMsid());
try {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Forwarding " + status + " to " + peer.getMsid());
}
sendStatus(peerName, status);
} catch (final Exception e) {
String msg = String.format("Caught exception while talking to %d", peer.getMsid());
s_logger.warn(msg);
s_logger.debug(msg, e);
}
}
}
public void sendStatus(final String strPeer, final String status) {
final ClusterServicePdu pdu = new ClusterServicePdu();
pdu.setSourcePeer(getSelfPeerName());
pdu.setDestPeer(strPeer);
pdu.setPduType(ClusterServicePdu.PDU_TYPE_STATUS_UPDATE);
pdu.setAgentId(0);
pdu.setJsonPackage(status);
pdu.setStopOnError(true);
addOutgoingClusterPdu(pdu);
}
@Override
public String execute(final String strPeer, final long agentId, final String cmds, final boolean stopOnError) {
if (s_logger.isDebugEnabled()) {
@ -1005,8 +1052,11 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
if (_mshostId != null) {
final ManagementServerHostVO mshost = _mshostDao.findByMsid(_msId);
final ManagementServerStatusVO mshostStatus = mshostStatusDao.findByMsId(mshost.getUuid());
mshost.setState(ManagementServerHost.State.Down);
mshostStatus.setLastJvmStop(new Date());
_mshostDao.update(_mshostId, mshost);
mshostStatusDao.update(mshostStatus.getId(), mshostStatus);
}
_heartbeatScheduler.shutdownNow();
@ -1141,7 +1191,10 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
return true;
} catch (final IOException e) {
if (e instanceof ConnectException) {
s_logger.error("Unable to ping management server at " + targetIp + ":" + mshost.getServicePort() + " due to ConnectException", e);
s_logger.error("Unable to ping management server at " + targetIp + ":" + mshost.getServicePort() + " due to ConnectException");
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to ping management server at " + targetIp + ":" + mshost.getServicePort() + " due to ConnectException", e);
}
return false;
}
} finally {
@ -1200,5 +1253,4 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
}
}
}
}

View File

@ -20,6 +20,7 @@ public class ClusterServicePdu {
public final static int PDU_TYPE_MESSAGE = 0;
public final static int PDU_TYPE_REQUEST = 1;
public final static int PDU_TYPE_RESPONSE = 2;
public final static int PDU_TYPE_STATUS_UPDATE = 3;
private long sequenceId;
private long ackSequenceId;

View File

@ -0,0 +1,184 @@
// 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.cluster;
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.management.ManagementServerStatus;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
@Entity
@Table(name = "mshost_status")
public class ManagementServerStatusVO implements ManagementServerStatus {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "ms_id", nullable = false)
private String msId;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="last_jvm_start")
private Date lastJvmStart;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="last_jvm_stop")
private Date lastJvmStop;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="last_system_boot")
private Date lastSystemBoot;
@Column(name="os_distribution")
private String osDistribution;
@Column(name="java_name")
private String javaName;
@Column(name="java_version")
private String javaVersion;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "updated")
private Date updated;
@Column(name = GenericDao.CREATED_COLUMN)
private Date created;
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
public ManagementServerStatusVO() {
}
@Override
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Override
public String getMsId() {
return msId;
}
public void setMsId(String msId) {
this.msId = msId;
}
@Override
public Date getLastJvmStart() {
return lastJvmStart;
}
public void setLastJvmStart(Date lastJvmStart) {
this.lastJvmStart = lastJvmStart;
}
@Override
public Date getLastJvmStop() {
return lastJvmStop;
}
public void setLastJvmStop(Date lastJvmStop) {
this.lastJvmStop = lastJvmStop;
}
@Override
public Date getLastSystemBoot() {
return lastSystemBoot;
}
public void setLastSystemBoot(Date lastSystemBoot) {
this.lastSystemBoot = lastSystemBoot;
}
@Override
public String getOsDistribution() {
return osDistribution;
}
public void setOsDistribution(String osDistribution) {
this.osDistribution = osDistribution;
}
@Override
public String getJavaName() {
return javaName;
}
public void setJavaName(String javaName) {
this.javaName = javaName;
}
@Override
public String getJavaVersion() {
return javaVersion;
}
public void setJavaVersion(String javaVersion) {
this.javaVersion = javaVersion;
}
@Override
public Date getUpdated() {
return updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
@Override
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
@Override
public Date getRemoved() {
return removed;
}
public void setRemoved(Date removedTime) {
removed = removedTime;
}
@Override
public String toString() {
return new ReflectionToStringBuilder(this, ToStringStyle.SIMPLE_STYLE).toString();
}
}

View File

@ -47,7 +47,12 @@ public interface ManagementServerHostDao extends GenericDao<ManagementServerHost
List<ManagementServerHostVO> listBy(ManagementServerHost.State... states);
public List<Long> listOrphanMsids();
/**
* Lists msids for which hosts are orphaned, i.e. msids that hosts refer as their owning ms whilst no mshost entry exists with those msids
*
* @return a list of non existing MS IDs
*/
List<Long> listOrphanMsids();
ManagementServerHostVO findOneInUpState(Filter filter);
}

View File

@ -0,0 +1,24 @@
// 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.cluster.dao;
import com.cloud.cluster.ManagementServerStatusVO;
import com.cloud.utils.db.GenericDao;
public interface ManagementServerStatusDao extends GenericDao<ManagementServerStatusVO, Long> {
ManagementServerStatusVO findByMsId(String msId);
}

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.cluster.dao;
import com.cloud.cluster.ManagementServerStatusVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import org.apache.commons.collections.CollectionUtils;
import java.util.List;
public class ManagementServerStatusDaoImpl extends GenericDaoBase<ManagementServerStatusVO, Long> implements ManagementServerStatusDao {
private final SearchBuilder<ManagementServerStatusVO> MsIdSearch;
public ManagementServerStatusDaoImpl() {
MsIdSearch = createSearchBuilder();
MsIdSearch.and("msid", MsIdSearch.entity().getMsId(), SearchCriteria.Op.EQ);
MsIdSearch.done();
}
@Override
public ManagementServerStatusVO findByMsId(String msId) {
SearchCriteria<ManagementServerStatusVO> sc = MsIdSearch.create();
sc.setParameters("msid", msId);
List<ManagementServerStatusVO> allServerStats = listIncludingRemovedBy(sc);
if (CollectionUtils.isNotEmpty(allServerStats)) {
return allServerStats.get(0);
}
return null;
}
}

View File

@ -46,7 +46,7 @@ import org.apache.log4j.Logger;
import static com.cloud.utils.AutoCloseableUtil.closeAutoCloseable;
public class DbUtil {
protected final static Logger s_logger = Logger.getLogger(DbUtil.class);
protected final static Logger LOGGER = Logger.getLogger(DbUtil.class);
private static Map<String, Connection> s_connectionForGlobalLocks = new HashMap<String, Connection>();
@ -54,7 +54,7 @@ public class DbUtil {
synchronized (s_connectionForGlobalLocks) {
if (forLock) {
if (s_connectionForGlobalLocks.get(name) != null) {
s_logger.error("Sanity check failed, global lock name " + name + " is already in use");
LOGGER.error("Sanity check failed, global lock name " + name + " is already in use");
assert (false);
}
@ -198,7 +198,7 @@ public class DbUtil {
public static boolean getGlobalLock(String name, int timeoutSeconds) {
Connection conn = getConnectionForGlobalLocks(name, true);
if (conn == null) {
s_logger.error("Unable to acquire DB connection for global lock system");
LOGGER.error("Unable to acquire DB connection for global lock system");
return false;
}
@ -211,15 +211,15 @@ public class DbUtil {
if (rs.getInt(1) > 0) {
return true;
} else {
if (s_logger.isDebugEnabled())
s_logger.debug("GET_LOCK() timed out on lock : " + name);
if (LOGGER.isDebugEnabled())
LOGGER.debug("GET_LOCK() timed out on lock : " + name);
}
}
}
} catch (SQLException e) {
s_logger.error("GET_LOCK() throws exception ", e);
LOGGER.error("GET_LOCK() throws exception ", e);
} catch (Throwable e) {
s_logger.error("GET_LOCK() throws exception ", e);
LOGGER.error("GET_LOCK() throws exception ", e);
}
removeConnectionForGlobalLocks(name);
@ -234,7 +234,7 @@ public class DbUtil {
public static boolean releaseGlobalLock(String name) {
try (Connection conn = getConnectionForGlobalLocks(name, false);) {
if (conn == null) {
s_logger.error("Unable to acquire DB connection for global lock system");
LOGGER.error("Unable to acquire DB connection for global lock system");
assert (false);
return false;
}
@ -245,13 +245,13 @@ public class DbUtil {
if (rs != null && rs.first()) {
return rs.getInt(1) > 0;
}
s_logger.error("releaseGlobalLock:RELEASE_LOCK() returns unexpected result");
LOGGER.error("releaseGlobalLock:RELEASE_LOCK() returns unexpected result");
}
}
} catch (SQLException e) {
s_logger.error("RELEASE_LOCK() throws exception ", e);
LOGGER.error("RELEASE_LOCK() throws exception ", e);
} catch (Throwable e) {
s_logger.error("RELEASE_LOCK() throws exception ", e);
LOGGER.error("RELEASE_LOCK() throws exception ", e);
}
return false;
}
@ -282,4 +282,24 @@ public class DbUtil {
closeAutoCloseable(connection, "exception while close connection.");
}
public static Map<String, String> getDbInfo(String type, String ... var) {
String vars = String.join(",", var);
Map<String, String> result = new HashMap<>();
String sql = String.format("SHOW %s WHERE FIND_IN_SET(Variable_name,?)",type);
try (TransactionLegacy txn = TransactionLegacy.open("metrics")) {
PreparedStatement pstmt = txn.prepareAutoCloseStatement(sql);
pstmt.setString(1, vars);
final ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
String variableName = rs.getString("Variable_name");
String value = rs.getString("value");
result.put(variableName, value);
}
} catch (SQLException e) {
LOGGER.error("failed to get the database status: " + e.getLocalizedMessage());
LOGGER.debug("failed to get the database status", e);
}
return result;
}
}

View File

@ -47,6 +47,7 @@ public class CloudStackContextLoaderListener extends ContextLoaderListener {
@Override
public void contextInitialized(ServletContextEvent event) {
log.trace("context initialized");
try {
cloudStackContext = new CloudStackSpringContext();
cloudStackContext.registerShutdownHook();
@ -66,11 +67,11 @@ public class CloudStackContextLoaderListener extends ContextLoaderListener {
@Override
protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) {
log.trace("customize context");
super.customizeContext(servletContext, applicationContext);
String[] newLocations = cloudStackContext.getConfigLocationsForWeb(configuredParentName, applicationContext.getConfigLocations());
applicationContext.setConfigLocations(newLocations);
}
}

View File

@ -0,0 +1,56 @@
// 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.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.context.CallContext;
import org.apache.cloudstack.metrics.MetricsService;
import org.apache.cloudstack.response.DbMetricsResponse;
import javax.inject.Inject;
@APICommand(name=ListDbMetricsCmd.APINAME, description = "list the db hosts and statistics",
responseObject = DbMetricsResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
responseView = ResponseObject.ResponseView.Full, since = "4.17.0", authorized = {RoleType.Admin})
public class ListDbMetricsCmd extends BaseCmd {
public static final String APINAME = "listDbMetrics";
@Inject
private MetricsService metricsService;
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
DbMetricsResponse response = metricsService.listDbMetrics();
response.setResponseName(getCommandName());
setResponseObject(response);
}
@Override
public String getCommandName() {
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
}
@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccountId();
}
}

View File

@ -0,0 +1,56 @@
// 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 org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.command.admin.management.ListMgmtsCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.metrics.MetricsService;
import org.apache.cloudstack.response.ManagementServerMetricsResponse;
import javax.inject.Inject;
import java.util.List;
@APICommand(name = ListMgmtsMetricsCmd.APINAME, description = "Lists Management Server metrics", responseObject = ManagementServerMetricsResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full,
since = "4.17.0", authorized = {RoleType.Admin})
public class ListMgmtsMetricsCmd extends ListMgmtsCmd {
public static final String APINAME = "listManagementServersMetrics";
@Parameter(name = MetricConstants.SYSTEM, type = CommandType.BOOLEAN, entityType = ManagementServerMetricsResponse.class, description = "include system level stats")
private boolean system;
@Inject
private MetricsService metricsService;
@Override
public String getCommandName() {
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
}
@Override
public void execute() {
ListResponse<ManagementServerResponse> managementServers = _queryService.listManagementServers(this);
final List<ManagementServerMetricsResponse> metricsResponses = metricsService.listManagementServerMetrics(managementServers.getResponses());
ListResponse<ManagementServerMetricsResponse> response = new ListResponse<>();
response.setResponses(metricsResponses, managementServers.getCount());
response.setResponseName(getCommandName());
setResponseObject(response);
}
}

View File

@ -0,0 +1,57 @@
// 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.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.context.CallContext;
import org.apache.cloudstack.metrics.MetricsService;
import org.apache.cloudstack.response.UsageServerMetricsResponse;
import javax.inject.Inject;
@APICommand(name = ListUsageServerMetricsCmd.APINAME, description = "Lists Usage Server metrics", responseObject = UsageServerMetricsResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full,
since = "4.17.0", authorized = {RoleType.Admin})
public class ListUsageServerMetricsCmd extends BaseCmd {
public static final String APINAME = "listUsageServerMetrics";
@Inject
private MetricsService metricsService;
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
UsageServerMetricsResponse usageServerMetrics = metricsService.listUsageServerMetrics();
usageServerMetrics.setResponseName(getCommandName());
setResponseObject(usageServerMetrics);
}
@Override
public String getCommandName() {
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
}
@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccountId();
}
}

View File

@ -0,0 +1,56 @@
// 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;
/**
* metric local api constants
*/
public interface MetricConstants {
String AGENT_COUNT = "agentcount";
String AVAILABLE_PROCESSORS = "availableprocessors";
String CONNECTIONS = "connections";
String DATABASE_IS_LOCAL = "dbislocal";
String DATABASE_LOAD_AVERAGES = "dbloadaverages";
String HEAP_MEMORY_USED = "heapmemoryused";
String HEAP_MEMORY_TOTAL = "heapmemorytotal";
String LAST_HEARTBEAT = "lastheartbeat";
String LAST_SUCCESSFUL_JOB = "lastsuccessfuljob";
String LOG_INFO = "loginfo";
String REPLICAS = "replicas";
String SESSIONS = "sessions";
String SYSTEM = "system";
String SYSTEM_CYCLES = "systemtotalcpucycles";
String SYSTEM_CYCLE_USAGE = "systemcycleusage";
String SYSTEM_LOAD_AVERAGES = "systemloadaverages";
String SYSTEM_MEMORY_FREE = "systemmemoryfree";
String SYSTEM_MEMORY_TOTAL = "systemmemorytotal";
String SYSTEM_MEMORY_USED = "systemmemoryused";
String SYSTEM_MEMORY_VIRTUALSIZE = "systemmemoryvirtualsize";
String THREADS_BLOCKED_COUNT = "threadsblockedcount";
String THREADS_DAEMON_COUNT = "threadsdaemoncount";
String THREADS_RUNNABLE_COUNT = "threadsrunnablecount";
String THREADS_TERMINATED_COUNT = "threadsteminatedcount";
String THREADS_TOTAL_COUNT = "threadstotalcount";
String THREADS_WAITING_COUNT = "threadswaitingcount";
String TLS_VERSIONS = "tlsversions";
String UPTIME = "uptime";
String USAGE_IS_LOCAL = "usageislocal";
String VERSION_COMMENT = "versioncomment";
String QUERIES = "queries";
String COLLECTION_TIME = "collectiontime";
String CPULOAD = "cpuload";
}

View File

@ -24,14 +24,18 @@ import org.apache.cloudstack.api.ListVMsUsageHistoryCmd;
import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.response.ClusterMetricsResponse;
import org.apache.cloudstack.response.DbMetricsResponse;
import org.apache.cloudstack.response.HostMetricsResponse;
import org.apache.cloudstack.response.InfrastructureResponse;
import org.apache.cloudstack.response.ManagementServerMetricsResponse;
import org.apache.cloudstack.response.StoragePoolMetricsResponse;
import org.apache.cloudstack.response.UsageServerMetricsResponse;
import org.apache.cloudstack.response.VmMetricsResponse;
import org.apache.cloudstack.response.VmMetricsStatsResponse;
import org.apache.cloudstack.response.VolumeMetricsResponse;
@ -47,6 +51,10 @@ public interface MetricsService extends PluggableService {
List<VmMetricsResponse> listVmMetrics(List<UserVmResponse> vmResponses);
List<StoragePoolMetricsResponse> listStoragePoolMetrics(List<StoragePoolResponse> poolResponses);
List<HostMetricsResponse> listHostMetrics(List<HostResponse> poolResponses);
List<ManagementServerMetricsResponse> listManagementServerMetrics(List<ManagementServerResponse> poolResponses);
List<ClusterMetricsResponse> listClusterMetrics(Pair<List<ClusterResponse>, Integer> clusterResponses);
List<ZoneMetricsResponse> listZoneMetrics(List<ZoneResponse> poolResponses);
UsageServerMetricsResponse listUsageServerMetrics();
DbMetricsResponse listDbMetrics();
}

View File

@ -24,14 +24,26 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.inject.Inject;
import com.cloud.server.DbStatsCollection;
import com.cloud.server.StatsCollector;
import com.cloud.usage.UsageJobVO;
import com.cloud.usage.dao.UsageJobDao;
import com.cloud.utils.db.DbProperties;
import com.cloud.utils.db.DbUtil;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.script.Script;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ListClustersMetricsCmd;
import org.apache.cloudstack.api.ListDbMetricsCmd;
import org.apache.cloudstack.api.ListHostsMetricsCmd;
import org.apache.cloudstack.api.ListInfrastructureCmd;
import org.apache.cloudstack.api.ListMgmtsMetricsCmd;
import org.apache.cloudstack.api.ListStoragePoolsMetricsCmd;
import org.apache.cloudstack.api.ListUsageServerMetricsCmd;
import org.apache.cloudstack.api.ListVMsMetricsCmd;
import org.apache.cloudstack.api.ListVMsUsageHistoryCmd;
import org.apache.cloudstack.api.ListVolumesMetricsCmd;
@ -41,15 +53,21 @@ import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.StatsResponse;
import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.management.ManagementServerHost.State;
import org.apache.cloudstack.response.ClusterMetricsResponse;
import org.apache.cloudstack.response.DbMetricsResponse;
import org.apache.cloudstack.response.HostMetricsResponse;
import org.apache.cloudstack.response.HostMetricsSummary;
import org.apache.cloudstack.response.InfrastructureResponse;
import org.apache.cloudstack.response.ManagementServerMetricsResponse;
import org.apache.cloudstack.response.StoragePoolMetricsResponse;
import org.apache.cloudstack.response.UsageServerMetricsResponse;
import org.apache.cloudstack.response.VmMetricsResponse;
import org.apache.cloudstack.response.VmMetricsStatsResponse;
import org.apache.cloudstack.response.VolumeMetricsResponse;
@ -58,7 +76,6 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.agent.api.VmStatsEntryBase;
import com.cloud.alert.AlertManager;
@ -86,6 +103,7 @@ import com.cloud.network.router.VirtualRouter;
import com.cloud.org.Cluster;
import com.cloud.org.Grouping;
import com.cloud.org.Managed;
import com.cloud.server.ManagementServerHostStats;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.utils.Pair;
@ -101,8 +119,15 @@ import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.dao.VmStatsDao;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.log4j.Logger;
import static com.cloud.utils.NumbersUtil.toReadableSize;
public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements MetricsService {
private static final Logger LOGGER = Logger.getLogger(MetricsServiceImpl.class);
@Inject
private DataCenterDao dataCenterDao;
@ -134,6 +159,8 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
protected UserVmDao userVmDao;
@Inject
protected VmStatsDao vmStatsDao;
@Inject
private UsageJobDao usageJobDao;
private static Gson gson = new Gson();
@ -141,16 +168,23 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
super();
}
private void updateHostMetrics(final Metrics metrics, final HostJoinVO host) {
metrics.incrTotalHosts();
metrics.addCpuAllocated(host.getCpuReservedCapacity() + host.getCpuUsedCapacity());
metrics.addMemoryAllocated(host.getMemReservedCapacity() + host.getMemUsedCapacity());
private Double findRatioValue(final String value) {
if (value != null) {
return Double.valueOf(value);
}
return 1.0;
}
private void updateHostMetrics(final HostMetrics hostMetrics, final HostJoinVO host) {
hostMetrics.incrTotalHosts();
hostMetrics.addCpuAllocated(host.getCpuReservedCapacity() + host.getCpuUsedCapacity());
hostMetrics.addMemoryAllocated(host.getMemReservedCapacity() + host.getMemUsedCapacity());
final HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId());
if (hostStats != null) {
metrics.addCpuUsedPercentage(hostStats.getCpuUtilization());
metrics.addMemoryUsed((long) hostStats.getUsedMemory());
metrics.setMaximumCpuUsage(hostStats.getCpuUtilization());
metrics.setMaximumMemoryUsage((long) hostStats.getUsedMemory());
hostMetrics.addCpuUsedPercentage(hostStats.getCpuUtilization());
hostMetrics.addMemoryUsed((long) hostStats.getUsedMemory());
hostMetrics.setMaximumCpuUsage(hostStats.getCpuUtilization());
hostMetrics.setMaximumMemoryUsage((long) hostStats.getUsedMemory());
}
}
/**
@ -517,54 +551,26 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
}
final Long clusterId = cluster.getId();
// Thresholds
final Double cpuThreshold = AlertManager.CPUCapacityThreshold.valueIn(clusterId);
final Double memoryThreshold = AlertManager.MemoryCapacityThreshold.valueIn(clusterId);
final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.valueIn(clusterId);
final Float memoryDisableThreshold = DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.valueIn(clusterId);
// CPU and memory capacities
final CapacityDaoImpl.SummedCapacity cpuCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_CPU, null, clusterId);
final CapacityDaoImpl.SummedCapacity memoryCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_MEMORY, null, clusterId);
final Metrics metrics = new Metrics(cpuCapacity, memoryCapacity);
final HostMetrics hostMetrics = new HostMetrics(cpuCapacity, memoryCapacity);
for (final Host host: hostDao.findByClusterId(clusterId)) {
if (host == null || host.getType() != Host.Type.Routing) {
continue;
}
if (host.getStatus() == Status.Up) {
metrics.incrUpResources();
hostMetrics.incrUpResources();
}
metrics.incrTotalResources();
updateHostMetrics(metrics, hostJoinDao.findById(host.getId()));
hostMetrics.incrTotalResources();
updateHostMetrics(hostMetrics, hostJoinDao.findById(host.getId()));
}
metricsResponse.setState(clusterResponse.getAllocationState(), clusterResponse.getManagedState());
metricsResponse.setResources(metrics.getUpResources(), metrics.getTotalResources());
// CPU
metricsResponse.setCpuTotal(metrics.getTotalCpu());
metricsResponse.setCpuAllocated(metrics.getCpuAllocated(), metrics.getTotalCpu());
if (metrics.getCpuUsedPercentage() > 0L) {
metricsResponse.setCpuUsed(metrics.getCpuUsedPercentage(), metrics.getTotalHosts());
metricsResponse.setCpuMaxDeviation(metrics.getMaximumCpuUsage(), metrics.getCpuUsedPercentage(), metrics.getTotalHosts());
}
// Memory
metricsResponse.setMemTotal(metrics.getTotalMemory());
metricsResponse.setMemAllocated(metrics.getMemoryAllocated(), metrics.getTotalMemory());
if (metrics.getMemoryUsed() > 0L) {
metricsResponse.setMemUsed(metrics.getMemoryUsed(), metrics.getTotalMemory());
metricsResponse.setMemMaxDeviation(metrics.getMaximumMemoryUsage(), metrics.getMemoryUsed(), metrics.getTotalHosts());
}
// CPU thresholds
metricsResponse.setCpuUsageThreshold(metrics.getCpuUsedPercentage(), metrics.getTotalHosts(), cpuThreshold);
metricsResponse.setCpuUsageDisableThreshold(metrics.getCpuUsedPercentage(), metrics.getTotalHosts(), cpuDisableThreshold);
metricsResponse.setCpuAllocatedThreshold(metrics.getCpuAllocated(), metrics.getTotalCpu(), cpuThreshold);
metricsResponse.setCpuAllocatedDisableThreshold(metrics.getCpuAllocated(), metrics.getTotalCpu(), cpuDisableThreshold);
// Memory thresholds
metricsResponse.setMemoryUsageThreshold(metrics.getMemoryUsed(), metrics.getTotalMemory(), memoryThreshold);
metricsResponse.setMemoryUsageDisableThreshold(metrics.getMemoryUsed(), metrics.getTotalMemory(), memoryDisableThreshold);
metricsResponse.setMemoryAllocatedThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryThreshold);
metricsResponse.setMemoryAllocatedDisableThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryDisableThreshold);
metricsResponse.setResources(hostMetrics.getUpResources(), hostMetrics.getTotalResources());
addHostCpuMetricsToResponse(metricsResponse, clusterId, hostMetrics);
addHostMemoryMetricsToResponse(metricsResponse, clusterId, hostMetrics);
metricsResponse.setHasAnnotation(clusterResponse.hasAnnotation());
metricsResponses.add(metricsResponse);
@ -572,6 +578,125 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
return metricsResponses;
}
private void addHostMemoryMetricsToResponse(HostMetricsSummary metricsResponse, Long clusterId, HostMetrics hostMetrics) {
final Long totalMemory = hostMetrics.getTotalMemory();
final Long memoryAllocated = hostMetrics.getMemoryAllocated();
final Long memoryUsed = hostMetrics.getMemoryUsed();
metricsResponse.setMemTotal(totalMemory);
metricsResponse.setMemAllocated(memoryAllocated, totalMemory);
if (memoryUsed > 0L) {
metricsResponse.setMemUsed(memoryUsed, totalMemory);
metricsResponse.setMemMaxDeviation(hostMetrics.getMaximumMemoryUsage(), memoryUsed, hostMetrics.getTotalHosts());
}
// thresholds
final Double memoryThreshold = (clusterId != null) ? AlertManager.MemoryCapacityThreshold.valueIn(clusterId) : AlertManager.MemoryCapacityThreshold.value();
final Float memoryDisableThreshold = (clusterId != null) ? DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.valueIn(clusterId) : DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.value();
metricsResponse.setMemoryUsageThreshold(memoryUsed, totalMemory, memoryThreshold);
metricsResponse.setMemoryUsageDisableThreshold(memoryUsed, totalMemory, memoryDisableThreshold);
metricsResponse.setMemoryAllocatedThreshold(memoryAllocated, totalMemory, memoryThreshold);
metricsResponse.setMemoryAllocatedDisableThreshold(memoryAllocated, totalMemory, memoryDisableThreshold);
}
private void addHostCpuMetricsToResponse(HostMetricsSummary metricsResponse, Long clusterId, HostMetrics hostMetrics) {
Long totalHosts = hostMetrics.getTotalHosts();
Long totalCpu = hostMetrics.getTotalCpu();
Long cpuAllocated = hostMetrics.getCpuAllocated();
final Double cpuUsedPercentage = hostMetrics.getCpuUsedPercentage();
metricsResponse.setCpuTotal(totalCpu);
metricsResponse.setCpuAllocated(cpuAllocated, totalCpu);
if (cpuUsedPercentage > 0L) {
metricsResponse.setCpuUsed(cpuUsedPercentage, totalHosts);
metricsResponse.setCpuMaxDeviation(hostMetrics.getMaximumCpuUsage(), cpuUsedPercentage, totalHosts);
}
// thresholds
final Double cpuThreshold = (clusterId != null) ? AlertManager.CPUCapacityThreshold.valueIn(clusterId) : AlertManager.CPUCapacityThreshold.value();
final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.valueIn(clusterId);
metricsResponse.setCpuUsageThreshold(cpuUsedPercentage, totalHosts, cpuThreshold);
metricsResponse.setCpuUsageDisableThreshold(cpuUsedPercentage, totalHosts, cpuDisableThreshold);
metricsResponse.setCpuAllocatedThreshold(cpuAllocated, totalCpu, cpuThreshold);
metricsResponse.setCpuAllocatedDisableThreshold(cpuAllocated, totalCpu, cpuDisableThreshold);
}
@Override
public List<ManagementServerMetricsResponse> listManagementServerMetrics(List<ManagementServerResponse> managementServerResponses) {
final List<ManagementServerMetricsResponse> metricsResponses = new ArrayList<>();
if(LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Getting metrics for %d MS hosts.", managementServerResponses.size()));
}
for (final ManagementServerResponse managementServerResponse: managementServerResponses) {
if(LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Processing metrics for MS hosts %s.", managementServerResponse.getId()));
}
ManagementServerMetricsResponse metricsResponse = new ManagementServerMetricsResponse();
try {
BeanUtils.copyProperties(metricsResponse, managementServerResponse);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("Bean copy result %s.", new ReflectionToStringBuilder(metricsResponse, ToStringStyle.SIMPLE_STYLE).toString()));
}
} catch (IllegalAccessException | InvocationTargetException e) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate zone metrics response.");
}
updateManagementServerMetrics(metricsResponse, managementServerResponse);
metricsResponses.add(metricsResponse);
}
return metricsResponses;
}
/**
* Get the transient/in memory data.
*/
private void updateManagementServerMetrics(ManagementServerMetricsResponse metricsResponse, ManagementServerResponse managementServerResponse) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Getting stats for %s[%s]", managementServerResponse.getName(), managementServerResponse.getId()));
}
ManagementServerHostStats status = ApiDBUtils.getManagementServerHostStatistics(managementServerResponse.getId());
if (status == null ) {
LOGGER.info(String.format("No status object found for MS %s - %s.", managementServerResponse.getName(), managementServerResponse.getId()));
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Status object found for MS %s - %s.", managementServerResponse.getName(), new ReflectionToStringBuilder(status)));
}
if (StatsCollector.MANAGEMENT_SERVER_STATUS_COLLECTION_INTERVAL.value() > 0) {
copyManagementServerStatusToResponse(metricsResponse, status);
}
}
}
private void copyManagementServerStatusToResponse(ManagementServerMetricsResponse metricsResponse, ManagementServerHostStats status) {
metricsResponse.setDbLocal(status.isDbLocal());
metricsResponse.setUsageLocal(status.isUsageLocal());
metricsResponse.setAvailableProcessors(status.getAvailableProcessors());
metricsResponse.setAgentCount(status.getAgentCount());
metricsResponse.setCollectionTime(status.getCollectionTime());
metricsResponse.setSessions(status.getSessions());
metricsResponse.setHeapMemoryUsed(status.getHeapMemoryUsed());
metricsResponse.setHeapMemoryTotal(status.getHeapMemoryTotal());
metricsResponse.setThreadsBlockedCount(status.getThreadsBlockedCount());
metricsResponse.setThreadsDaemonCount(status.getThreadsDaemonCount());
metricsResponse.setThreadsRunnableCount(status.getThreadsRunnableCount());
metricsResponse.setThreadsTerminatedCount(status.getThreadsTerminatedCount());
metricsResponse.setThreadsTotalCount(status.getThreadsTotalCount());
metricsResponse.setThreadsWaitingCount(status.getThreadsWaitingCount());
metricsResponse.setSystemMemoryTotal(toReadableSize(status.getSystemMemoryTotal()));
metricsResponse.setSystemMemoryFree(toReadableSize(status.getSystemMemoryFree()));
// we are not adding metricsResponse.setSystemMemoryUsed(toReadableSize(status.getSystemMemoryUsed())); as the value is confusing and arguably wrong
metricsResponse.setSystemMemoryVirtualSize(toReadableSize(status.getSystemMemoryVirtualSize()));
metricsResponse.setLogInfo(status.getLogInfo());
metricsResponse.setSystemTotalCpuCycles(status.getSystemTotalCpuCycles());
metricsResponse.setSystemLoadAverages(status.getSystemLoadAverages());
long[] cycles = status.getSystemCyclesUsage();
metricsResponse.setSystemCycleUsage(cycles);
double currentLoad = 100.0 * (cycles[0] + cycles[1]) / (cycles[0] + cycles[1] + cycles[2]);
metricsResponse.setCpuLoad(currentLoad);
metricsResponse.setKernelVersion(status.getKernelVersion());
}
@Override
public List<ZoneMetricsResponse> listZoneMetrics(List<ZoneResponse> zoneResponses) {
final List<ZoneMetricsResponse> metricsResponses = new ArrayList<>();
@ -590,83 +715,173 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
}
final Long zoneId = zone.getId();
// Thresholds
final Double cpuThreshold = AlertManager.CPUCapacityThreshold.value();
final Double memoryThreshold = AlertManager.MemoryCapacityThreshold.value();
final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.value();
final Float memoryDisableThreshold = DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.value();
// CPU and memory capacities
final CapacityDaoImpl.SummedCapacity cpuCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_CPU, zoneId, null);
final CapacityDaoImpl.SummedCapacity memoryCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_MEMORY, zoneId, null);
final Metrics metrics = new Metrics(cpuCapacity, memoryCapacity);
final HostMetrics hostMetrics = new HostMetrics(cpuCapacity, memoryCapacity);
for (final Cluster cluster : clusterDao.listClustersByDcId(zoneId)) {
if (cluster == null) {
continue;
}
metrics.incrTotalResources();
hostMetrics.incrTotalResources();
if (cluster.getAllocationState() == Grouping.AllocationState.Enabled
&& cluster.getManagedState() == Managed.ManagedState.Managed) {
metrics.incrUpResources();
hostMetrics.incrUpResources();
}
for (final Host host: hostDao.findByClusterId(cluster.getId())) {
if (host == null || host.getType() != Host.Type.Routing) {
continue;
}
updateHostMetrics(metrics, hostJoinDao.findById(host.getId()));
updateHostMetrics(hostMetrics, hostJoinDao.findById(host.getId()));
}
}
metricsResponse.setHasAnnotation(zoneResponse.hasAnnotation());
metricsResponse.setState(zoneResponse.getAllocationState());
metricsResponse.setResource(metrics.getUpResources(), metrics.getTotalResources());
metricsResponse.setResource(hostMetrics.getUpResources(), hostMetrics.getTotalResources());
final Long totalHosts = hostMetrics.getTotalHosts();
// CPU
metricsResponse.setCpuTotal(metrics.getTotalCpu());
metricsResponse.setCpuAllocated(metrics.getCpuAllocated(), metrics.getTotalCpu());
if (metrics.getCpuUsedPercentage() > 0L) {
metricsResponse.setCpuUsed(metrics.getCpuUsedPercentage(), metrics.getTotalHosts());
metricsResponse.setCpuMaxDeviation(metrics.getMaximumCpuUsage(), metrics.getCpuUsedPercentage(), metrics.getTotalHosts());
}
addHostCpuMetricsToResponse(metricsResponse, null, hostMetrics);
// Memory
metricsResponse.setMemTotal(metrics.getTotalMemory());
metricsResponse.setMemAllocated(metrics.getMemoryAllocated(), metrics.getTotalMemory());
if (metrics.getMemoryUsed() > 0L) {
metricsResponse.setMemUsed(metrics.getMemoryUsed(), metrics.getTotalMemory());
metricsResponse.setMemMaxDeviation(metrics.getMaximumMemoryUsage(), metrics.getMemoryUsed(), metrics.getTotalHosts());
}
// CPU thresholds
metricsResponse.setCpuUsageThreshold(metrics.getCpuUsedPercentage(), metrics.getTotalHosts(), cpuThreshold);
metricsResponse.setCpuUsageDisableThreshold(metrics.getCpuUsedPercentage(), metrics.getTotalHosts(), cpuDisableThreshold);
metricsResponse.setCpuAllocatedThreshold(metrics.getCpuAllocated(), metrics.getTotalCpu(), cpuThreshold);
metricsResponse.setCpuAllocatedDisableThreshold(metrics.getCpuAllocated(), metrics.getTotalCpu(), cpuDisableThreshold);
// Memory thresholds
metricsResponse.setMemoryUsageThreshold(metrics.getMemoryUsed(), metrics.getTotalMemory(), memoryThreshold);
metricsResponse.setMemoryUsageDisableThreshold(metrics.getMemoryUsed(), metrics.getTotalMemory(), memoryDisableThreshold);
metricsResponse.setMemoryAllocatedThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryThreshold);
metricsResponse.setMemoryAllocatedDisableThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryDisableThreshold);
addHostMemoryMetricsToResponse(metricsResponse, null, hostMetrics);
metricsResponses.add(metricsResponse);
}
return metricsResponses;
}
@Override
public UsageServerMetricsResponse listUsageServerMetrics() {
UsageServerMetricsResponse response = new UsageServerMetricsResponse();
response.setCollectionTime(new Date());
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
response.setLastHeartbeat(usageJobDao.getLastHeartbeat());
response.setState(isUsageRunning() ? State.Up : State.Down);
UsageJobVO job = usageJobDao.getNextImmediateJob();
if (job == null) {
job = usageJobDao.getLastJob();
}
response.setHostname(job == null ? "N/A" : job.getHost());
response.setLastSuccessfulJob(new Date(usageJobDao.getLastJobSuccessDateMillis()));
} finally {
txn.close();
TransactionLegacy swap = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
swap.close();
}
response.setObjectName("usageMetrics");
return response;
}
/**
Some TODOs left here
State (Up / Down) , makes no sense (no db no cloudstack)
Average Queries Per Second
Buffer Pool Utilization (buffer pool is used to cache the table data in memory and is accessed repeatedly by queries without requiring any disk I/O).
any other relevant stats (if useful) to the response from the sql status variables.
* @return the {@see DbMetricsResponse} containing the state of the DB
*/
@Override
public DbMetricsResponse listDbMetrics() {
DbMetricsResponse response = new DbMetricsResponse();
response.setHostname(dbHostName());
response.setReplicas(dbReplicas());
getDynamicDataFromDB(response);
getStaticDataFromDB(response);
getQueryHistory(response);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(new ReflectionToStringBuilder(response));
}
response.setObjectName("dbMetrics");
return response;
}
private void getQueryHistory(DbMetricsResponse response) {
Map<String, Object> dbStats = ApiDBUtils.getDbStatistics();
if (dbStats != null) {
response.setQueries((Integer)dbStats.get(DbStatsCollection.queries));
response.setUptime((Integer)dbStats.get(DbStatsCollection.uptime));
}
List<Double> loadHistory = (List<Double>) dbStats.get(DbStatsCollection.loadAvarages);
double[] loadAverages = new double[loadHistory.size()];
int index = 0;
for (Double d : loadHistory) {
loadAverages[index++] = d;
}
response.setLoadAverages(loadAverages);
response.setCollectionTime((Date) dbStats.get(DbStatsCollection.collectionTime));
}
private void getStaticDataFromDB(DbMetricsResponse response) {
Map<String, String> vars = DbUtil.getDbInfo(DbStatsCollection.variables, DbStatsCollection.version, DbStatsCollection.versionComment);
response.setVersion(vars.get(DbStatsCollection.version));
response.setVersionComment(vars.get(DbStatsCollection.versionComment));
}
private void getDynamicDataFromDB(DbMetricsResponse response) {
Map<String, String> stats = DbUtil.getDbInfo(DbStatsCollection.status, DbStatsCollection.connections, DbStatsCollection.currentTlsVersion);
response.setConnections(Integer.parseInt(stats.get(DbStatsCollection.connections)));
response.setTlsVersions(stats.get(DbStatsCollection.currentTlsVersion));
}
private String dbHostName() {
Properties p = DbProperties.getDbProperties();
return p.getProperty("db.cloud.host");
}
private String[] dbReplicas() {
Properties p = DbProperties.getDbProperties();
return p.getProperty("db.cloud.replicas","").split(",");
}
/**
* Returns whether a local usage server is running.
* Note that this might not be the one actually doing the usage aggregation at this moment.
* @return true if the service is active.
*/
protected boolean isUsageRunning() {
boolean local = false;
String usageStatus = Script.runSimpleBashScript("systemctl status cloudstack-usage | grep \" Active:\"");
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("The current usage status is: %s.", usageStatus));
}
if (StringUtils.isNotBlank(usageStatus)) {
local = usageStatus.contains("running");
}
return local;
}
@Override
public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>();
cmdList.add(ListInfrastructureCmd.class);
cmdList.add(ListVolumesMetricsCmd.class);
cmdList.add(ListVMsMetricsCmd.class);
cmdList.add(ListStoragePoolsMetricsCmd.class);
cmdList.add(ListHostsMetricsCmd.class);
cmdList.add(ListClustersMetricsCmd.class);
cmdList.add(ListDbMetricsCmd.class);
cmdList.add(ListHostsMetricsCmd.class);
cmdList.add(ListInfrastructureCmd.class);
cmdList.add(ListMgmtsMetricsCmd.class);
cmdList.add(ListStoragePoolsMetricsCmd.class);
cmdList.add(ListUsageServerMetricsCmd.class);
cmdList.add(ListVMsMetricsCmd.class);
cmdList.add(ListVolumesMetricsCmd.class);
cmdList.add(ListZonesMetricsCmd.class);
cmdList.add(ListVMsUsageHistoryCmd.class);
return cmdList;
}
private class Metrics {
private class HostMetrics {
// CPU metrics
private Long totalCpu = 0L;
private Long cpuAllocated = 0L;
@ -682,7 +897,7 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
private Long totalResources = 0L;
private Long upResources = 0L;
public Metrics(final CapacityDaoImpl.SummedCapacity totalCpu, final CapacityDaoImpl.SummedCapacity totalMemory) {
public HostMetrics(final CapacityDaoImpl.SummedCapacity totalCpu, final CapacityDaoImpl.SummedCapacity totalMemory) {
if (totalCpu != null) {
this.totalCpu = totalCpu.getTotalCapacity();
}

View File

@ -21,7 +21,7 @@ import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.response.ClusterResponse;
public class ClusterMetricsResponse extends ClusterResponse {
public class ClusterMetricsResponse extends ClusterResponse implements HostMetricsSummary {
@SerializedName("state")
@Param(description = "state of the cluster")
private String state;

View File

@ -0,0 +1,107 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.response;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.MetricConstants;
import java.util.Date;
public class DbMetricsResponse extends BaseResponse {
@SerializedName(MetricConstants.COLLECTION_TIME)
@Param(description = "the time these statistics were collected")
private Date collectionTime;
@SerializedName(ApiConstants.HOST_NAME)
@Param(description = "the name of the active usage server")
private String hostname;
@SerializedName(MetricConstants.REPLICAS)
@Param(description = "the state of the usage server")
private String[] replicas;
@SerializedName(MetricConstants.CONNECTIONS)
@Param(description = "the number of connections to the DB")
private int connections;
@SerializedName(MetricConstants.UPTIME)
@Param(description = "the uptime of the DB in seconds")
private int uptime;
@SerializedName(MetricConstants.TLS_VERSIONS)
@Param(description = "the tls versions currently in use (accepted) by the DB")
private String tlsVersions;
@SerializedName(ApiConstants.VERSION)
@Param(description = "the version of the currently running DB")
private String version;
@SerializedName(MetricConstants.VERSION_COMMENT)
@Param(description = "the version of the currently running DB")
private String versionComment;
@SerializedName(MetricConstants.QUERIES)
@Param(description = "the number of queries performed on the DB")
private int queries;
@SerializedName(MetricConstants.DATABASE_LOAD_AVERAGES)
@Param(description = "the last measured load averages on the DB")
private double[] loadAverages;
public void setHostname(String hostname) {
this.hostname = hostname;
}
public void setReplicas(String[] replicas) {
this.replicas = replicas;
}
public void setConnections(int connections) {
this.connections = connections;
}
public void setUptime(int uptime) {
this.uptime = uptime;
}
public void setTlsVersions(String tlsVersions) {
this.tlsVersions = tlsVersions;
}
public void setVersion(String version) {
this.version = version;
}
public void setVersionComment(String versionComment) {
this.versionComment = versionComment;
}
public void setQueries(int queries) {
this.queries = queries;
}
public void setLoadAverages(double [] loadAverages) {
this.loadAverages = loadAverages;
}
public void setCollectionTime(Date collectionTime) {
this.collectionTime = collectionTime;
}
}

View File

@ -0,0 +1,51 @@
// 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.response;
public interface HostMetricsSummary {
void setCpuTotal(Long totalCpu);
void setCpuAllocated(Long cpuAllocated, Long totalCpu);
void setCpuUsed(Double cpuUsedPercentage, Long totalHosts);
void setCpuMaxDeviation(Double maximumCpuUsage, Double cpuUsedPercentage, Long totalHosts);
void setCpuUsageThreshold(Double cpuUsedPercentage, Long totalHosts, Double cpuThreshold);
void setCpuUsageDisableThreshold(Double cpuUsedPercentage, Long totalHosts, Float cpuDisableThreshold);
void setCpuAllocatedThreshold(Long cpuAllocated, Long totalCpu, Double cpuThreshold);
void setCpuAllocatedDisableThreshold(Long cpuAllocated, Long totalCpu, Float cpuDisableThreshold);
void setMemTotal(Long totalMemory);
void setMemAllocated(Long memoryAllocated, Long totalMemory);
void setMemUsed(Long memoryUsed, Long totalMemory);
void setMemMaxDeviation(Long maximumMemoryUsage, Long memoryUsed, Long totalHosts);
void setMemoryUsageThreshold(Long memoryUsed, Long totalMemory, Double memoryThreshold);
void setMemoryUsageDisableThreshold(Long memoryUsed, Long totalMemory, Float memoryDisableThreshold);
void setMemoryAllocatedThreshold(Long memoryAllocated, Long totalMemory, Double memoryThreshold);
void setMemoryAllocatedDisableThreshold(Long memoryAllocated, Long totalMemory, Float memoryDisableThreshold);
}

View File

@ -0,0 +1,211 @@
// 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.response;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.MetricConstants;
import org.apache.cloudstack.api.response.ManagementServerResponse;
import java.util.Date;
public class ManagementServerMetricsResponse extends ManagementServerResponse {
@SerializedName(MetricConstants.AVAILABLE_PROCESSORS)
@Param(description = "the number of processors available to the JVM")
private Integer availableProcessors;
@SerializedName(MetricConstants.AGENT_COUNT)
@Param(description = "the number of agents this Management Server is responsible for")
private Integer agentCount;
@SerializedName(MetricConstants.SESSIONS)
@Param(description = "the number of client sessions active on this Management Server")
private Long sessions;
@SerializedName(MetricConstants.HEAP_MEMORY_USED)
@Param(description = "the amount of memory used by this Management Server")
private Long heapMemoryUsed;
@SerializedName(MetricConstants.HEAP_MEMORY_TOTAL)
@Param(description = "the amount of memory allocated to this Management Server")
private Long heapMemoryTotal;
@SerializedName(MetricConstants.THREADS_BLOCKED_COUNT)
@Param(description = "The number of blocked threads")
private Integer threadsBlockedCount;
@SerializedName(MetricConstants.THREADS_DAEMON_COUNT)
@Param(description = "The number of daemon threads")
private Integer threadsDaemonCount;
@SerializedName(MetricConstants.THREADS_RUNNABLE_COUNT)
@Param(description = "The number of runnable threads")
private Integer threadsRunnableCount;
@SerializedName(MetricConstants.THREADS_TERMINATED_COUNT)
@Param(description = "The number of terminated threads")
private Integer threadsTerminatedCount;
@SerializedName(MetricConstants.THREADS_TOTAL_COUNT)
@Param(description = "The number of threads")
private Integer threadsTotalCount;
@SerializedName(MetricConstants.THREADS_WAITING_COUNT)
@Param(description = "The number of waiting threads")
private Integer threadsWaitingCount;
@SerializedName(MetricConstants.SYSTEM_MEMORY_TOTAL)
@Param(description = "Total system memory")
private String systemMemoryTotal;
@SerializedName(MetricConstants.SYSTEM_MEMORY_FREE)
@Param(description = "Free system memory")
private String systemMemoryFree;
@SerializedName(MetricConstants.SYSTEM_MEMORY_USED)
@Param(description = "Amount of memory used")
private String systemMemoryUsed;
@SerializedName(MetricConstants.SYSTEM_MEMORY_VIRTUALSIZE)
@Param(description = "Virtual size of the fully loaded process")
private String systemMemoryVirtualSize;
@SerializedName(MetricConstants.LOG_INFO)
@Param(description = "the log files and their usage on disk")
private String logInfo;
@SerializedName(MetricConstants.SYSTEM_CYCLES)
@Param(description = "the total system cpu capacity")
private Double systemTotalCpuCycles;
@SerializedName(MetricConstants.SYSTEM_LOAD_AVERAGES)
@Param(description = "the load averages for 1 5 and 15 minutes")
private double[] systemLoadAverages;
@SerializedName(MetricConstants.SYSTEM_CYCLE_USAGE)
@Param(description = "the system load for user, and system processes and the system idle cycles")
private long[] systemCycleUsage;
@SerializedName(MetricConstants.DATABASE_IS_LOCAL)
@Param(description = "the system is running against a local database")
private Boolean dbLocal;
@SerializedName(MetricConstants.USAGE_IS_LOCAL)
@Param(description = "the system has a usage server running locally")
private Boolean usageLocal;
@SerializedName(MetricConstants.CPULOAD)
@Param(description = "the current cpu load")
private String cpuLoad;
@SerializedName(MetricConstants.COLLECTION_TIME)
@Param(description = "the time these statistics were collected")
private Date collectionTime;
public void setAvailableProcessors(int availableProcessors) {
this.availableProcessors = availableProcessors;
}
public void setAgentCount(int agentCount) {
this.agentCount = agentCount;
}
public void setSessions(long sessions) {
this.sessions = sessions;
}
public void setHeapMemoryUsed(long heapMemoryUsed) {
this.heapMemoryUsed = heapMemoryUsed;
}
public void setHeapMemoryTotal(long heapMemoryTotal) {
this.heapMemoryTotal = heapMemoryTotal;
}
public void setThreadsBlockedCount(int threadsBlockedCount) {
this.threadsBlockedCount = threadsBlockedCount;
}
public void setThreadsDaemonCount(int threadsDaemonCount) {
this.threadsDaemonCount = threadsDaemonCount;
}
public void setThreadsRunnableCount(int threadsRunnableCount) {
this.threadsRunnableCount = threadsRunnableCount;
}
public void setThreadsTerminatedCount(int threadsTerminatedCount) {
this.threadsTerminatedCount = threadsTerminatedCount;
}
public void setThreadsTotalCount(int threadsTotalCount) {
this.threadsTotalCount = threadsTotalCount;
}
public void setThreadsWaitingCount(int threadsWaitingCount) {
this.threadsWaitingCount = threadsWaitingCount;
}
public void setSystemMemoryTotal(String systemMemoryTotal) {
this.systemMemoryTotal = systemMemoryTotal;
}
public void setSystemMemoryFree(String systemMemoryFree) {
this.systemMemoryFree = systemMemoryFree;
}
public void setSystemMemoryUsed(String systemMemoryUsed) {
this.systemMemoryUsed = systemMemoryUsed;
}
public void setSystemMemoryVirtualSize(String systemMemoryVirtualSize) {
this.systemMemoryVirtualSize = systemMemoryVirtualSize;
}
public void setLogInfo(String logInfo) {
this.logInfo = logInfo;
}
public void setSystemTotalCpuCycles(double systemTotalCpuCycles) {
this.systemTotalCpuCycles = systemTotalCpuCycles;
}
public void setSystemLoadAverages(double[] systemLoadAverages) {
this.systemLoadAverages = systemLoadAverages;
}
public void setSystemCycleUsage(long[] systemCycleUsage) {
this.systemCycleUsage = systemCycleUsage;
}
public void setDbLocal(boolean dbLocal) {
this.dbLocal = dbLocal;
}
public void setUsageLocal(boolean usageLocal) {
this.usageLocal = usageLocal;
}
public void setCollectionTime(Date collectionTime) {
this.collectionTime = collectionTime;
}
public void setCpuLoad(double cpuLoad) {
this.cpuLoad = String.format("%.2f %%",cpuLoad);
}
}

View File

@ -0,0 +1,68 @@
// 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.response;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.MetricConstants;
import org.apache.cloudstack.management.ManagementServerHost.State;
import java.util.Date;
public class UsageServerMetricsResponse extends BaseResponse {
@SerializedName(MetricConstants.COLLECTION_TIME)
@Param(description = "the time these statistics were collected")
private Date collectionTime;
@SerializedName(ApiConstants.HOST_NAME)
@Param(description = "the name of the active usage server")
private String hostname;
@SerializedName(ApiConstants.STATE)
@Param(description = "the state of the usage server")
private State state;
@SerializedName(MetricConstants.LAST_HEARTBEAT)
@Param(description = "the last time this Usage Server checked for jobs")
private Date lastHeartbeat;
@SerializedName(MetricConstants.LAST_SUCCESSFUL_JOB)
@Param(description = "the last time a usage job successfully completed")
private Date lastSuccessfulJob;
public void setCollectionTime(Date collectionTime) {
this.collectionTime = collectionTime;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public void setState(State state) {
this.state = state;
}
public void setLastHeartbeat(Date lastHeartbeat) {
this.lastHeartbeat = lastHeartbeat;
}
public void setLastSuccessfulJob(Date lastSuccessfulJob) {
this.lastSuccessfulJob = lastSuccessfulJob;
}
}

View File

@ -21,7 +21,7 @@ import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.response.ZoneResponse;
public class ZoneMetricsResponse extends ZoneResponse {
public class ZoneMetricsResponse extends ZoneResponse implements HostMetricsSummary {
@SerializedName("state")
@Param(description = "state of the cluster")
private String state;

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.metrics;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@ -47,6 +48,7 @@ import com.cloud.vm.VmStatsVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VmStatsDao;
@RunWith(MockitoJUnitRunner.class)
public class MetricsServiceImplTest {

View File

@ -170,6 +170,16 @@
<groupId>org.influxdb</groupId>
<artifactId>influxdb-java</artifactId>
</dependency>
<dependency>
<groupId>com.codahale.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.codahale.metrics</groupId>
<artifactId>metrics-jvm</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -189,6 +189,7 @@ import com.cloud.resource.ResourceManager;
import com.cloud.resource.icon.ResourceIconVO;
import com.cloud.resource.icon.dao.ResourceIconDao;
import com.cloud.server.ManagementServer;
import com.cloud.server.ManagementServerHostStats;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceManagerUtil;
import com.cloud.server.ResourceMetaDataService;
@ -990,6 +991,14 @@ public class ApiDBUtils {
return s_statsCollector.getHostStats(hostId);
}
public static ManagementServerHostStats getManagementServerHostStatistics(String mgmtSrvrUuid) {
return s_statsCollector.getManagementServerHostStats(mgmtSrvrUuid);
}
public static Map<String,Object> getDbStatistics() {
return s_statsCollector.getDbStats();
}
public static StorageStats getStoragePoolStatistics(long id) {
return s_statsCollector.getStoragePoolStats(id);
}

View File

@ -0,0 +1,90 @@
// 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.api;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.apache.log4j.Logger;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@WebListener
public class ApiSessionListener implements HttpSessionListener, ServletRequestListener {
public static final Logger LOGGER = Logger.getLogger(ApiSessionListener.class.getName());
private static final String ATTRIBUTE_NAME = "SessionCounter";
private static Map<HttpSession, Object> sessions = new ConcurrentHashMap<>();
private static long sessionCount;
public ApiSessionListener() {
sessionCount = 0;
}
/**
* @return the internal adminstered session count
*/
public static long getSessionCount() {
return sessionCount;
}
/**
* @return the size of the internal {@see Map} of sessions
*/
public static long getNumberOfSessions() {
return sessions.size();
}
public void sessionCreated(HttpSessionEvent event) {
LOGGER.debug("Session created by Id : " + event.getSession().getId() + " , session: " + event.getSession().toString() + " , source: " + event.getSource().toString() + " , event: " + event.toString());
synchronized (this) {
HttpSession session = event.getSession();
sessions.put(session, event.getSource());
sessionCount++;
}
LOGGER.debug("Sessions count: " + sessions);
}
public void sessionDestroyed(HttpSessionEvent event) {
LOGGER.debug("Session destroyed by Id : " + event.getSession().getId() + " , session: " + event.getSession().toString() + " , source: " + event.getSource().toString() + " , event: " + event.toString());
synchronized (this) {
sessionCount--;
sessions.remove(event.getSession());
}
LOGGER.debug("Sessions count: " + sessions);
}
@Override
public void requestDestroyed(ServletRequestEvent event) {
LOGGER.debug("request destroyed");
}
@Override
public void requestInitialized(ServletRequestEvent event) {
LOGGER.debug("request initialized");
HttpServletRequest request = (HttpServletRequest) event.getServletRequest();
HttpSession session = request.getSession();
if (session.isNew()) {
synchronized (this) {
// replace the source object for the address
sessions.put(session, request.getRemoteAddr());
}
}
}
}

View File

@ -119,14 +119,12 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -142,6 +140,7 @@ import com.cloud.api.query.dao.HostJoinDao;
import com.cloud.api.query.dao.HostTagDao;
import com.cloud.api.query.dao.ImageStoreJoinDao;
import com.cloud.api.query.dao.InstanceGroupJoinDao;
import com.cloud.api.query.dao.ManagementServerJoinDao;
import com.cloud.api.query.dao.ProjectAccountJoinDao;
import com.cloud.api.query.dao.ProjectInvitationJoinDao;
import com.cloud.api.query.dao.ProjectJoinDao;
@ -165,6 +164,7 @@ import com.cloud.api.query.vo.HostJoinVO;
import com.cloud.api.query.vo.HostTagVO;
import com.cloud.api.query.vo.ImageStoreJoinVO;
import com.cloud.api.query.vo.InstanceGroupJoinVO;
import com.cloud.api.query.vo.ManagementServerJoinVO;
import com.cloud.api.query.vo.ProjectAccountJoinVO;
import com.cloud.api.query.vo.ProjectInvitationJoinVO;
import com.cloud.api.query.vo.ProjectJoinVO;
@ -176,8 +176,6 @@ import com.cloud.api.query.vo.TemplateJoinVO;
import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.api.query.vo.VolumeJoinVO;
import com.cloud.cluster.ManagementServerHostVO;
import com.cloud.cluster.dao.ManagementServerHostDao;
import com.cloud.dc.DedicatedResourceVO;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.domain.Domain;
@ -213,7 +211,6 @@ import com.cloud.server.ResourceManagerUtil;
import com.cloud.server.ResourceMetaDataService;
import com.cloud.server.ResourceTag;
import com.cloud.server.ResourceTag.ResourceObjectType;
import com.cloud.server.TaggedResourceService;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
@ -228,7 +225,6 @@ import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.StoragePoolTagsDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateDetailsDao;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.tags.ResourceTagVO;
@ -337,9 +333,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Inject
private AccountDao _accountDao;
@Inject
private ConfigurationDao _configDao;
@Inject
private AccountJoinDao _accountJoinDao;
@ -396,9 +389,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Inject
private ResourceMetaDataService _resourceMetaDataMgr;
@Inject
private TaggedResourceService _taggedResourceMgr;
@Inject
private ResourceManagerUtil resourceManagerUtil;
@ -424,10 +414,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
private DataStoreManager dataStoreManager;
@Inject
ManagementServerHostDao managementServerHostDao;
@Inject
VMTemplateDetailsDao vmTemplateDetailsDao;
ManagementServerJoinDao managementServerJoinDao;
@Inject
public VpcVirtualNetworkApplianceService routerService;
@ -438,9 +425,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Inject
private RouterHealthCheckResultDao routerHealthCheckResultDao;
@Inject
private TemplateDataStoreDao templateDataStoreDao;
@Inject
private PrimaryDataStoreDao _storagePoolDao;
@ -4310,10 +4294,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Override
public ListResponse<ManagementServerResponse> listManagementServers(ListMgmtsCmd cmd) {
ListResponse<ManagementServerResponse> response = new ListResponse<>();
Pair<List<ManagementServerHostVO>, Integer> result = listManagementServersInternal(cmd);
Pair<List<ManagementServerJoinVO>, Integer> result = listManagementServersInternal(cmd);
List<ManagementServerResponse> hostResponses = new ArrayList<>();
for (ManagementServerHostVO host : result.first()) {
for (ManagementServerJoinVO host : result.first()) {
ManagementServerResponse hostResponse = createManagementServerResponse(host);
hostResponses.add(hostResponse);
}
@ -4322,27 +4306,33 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
return response;
}
protected Pair<List<ManagementServerHostVO>, Integer> listManagementServersInternal(ListMgmtsCmd cmd) {
protected Pair<List<ManagementServerJoinVO>, Integer> listManagementServersInternal(ListMgmtsCmd cmd) {
Long id = cmd.getId();
String name = cmd.getHostName();
SearchBuilder<ManagementServerHostVO> sb = managementServerHostDao.createSearchBuilder();
SearchCriteria<ManagementServerHostVO> sc = sb.create();
SearchBuilder<ManagementServerJoinVO> sb = managementServerJoinDao.createSearchBuilder();
SearchCriteria<ManagementServerJoinVO> sc = sb.create();
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (name != null) {
sc.addAnd("name", SearchCriteria.Op.EQ, name);
}
return managementServerHostDao.searchAndCount(sc, null);
return managementServerJoinDao.searchAndCount(sc, null);
}
protected ManagementServerResponse createManagementServerResponse(ManagementServerHostVO mgmt) {
protected ManagementServerResponse createManagementServerResponse(ManagementServerJoinVO mgmt) {
ManagementServerResponse mgmtResponse = new ManagementServerResponse();
mgmtResponse.setId(mgmt.getUuid());
mgmtResponse.setName(mgmt.getName());
mgmtResponse.setState(mgmt.getState());
mgmtResponse.setVersion(mgmt.getVersion());
mgmtResponse.setJavaVersion(mgmt.getJavaVersion());
mgmtResponse.setJavaDistribution(mgmt.getJavaName());
mgmtResponse.setOsDistribution(mgmt.getOsDistribution());
mgmtResponse.setLastServerStart(mgmt.getLastJvmStart());
mgmtResponse.setLastServerStop(mgmt.getLastJvmStop());
mgmtResponse.setLastBoot(mgmt.getLastSystemBoot());
mgmtResponse.setObjectName("managementserver");
return mgmtResponse;
}

View File

@ -0,0 +1,23 @@
// 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.api.query.dao;
import com.cloud.api.query.vo.ManagementServerJoinVO;
import com.cloud.utils.db.GenericDao;
public interface ManagementServerJoinDao extends GenericDao<ManagementServerJoinVO, Long> {
}

View File

@ -0,0 +1,23 @@
// 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.api.query.dao;
import com.cloud.api.query.vo.ManagementServerJoinVO;
import com.cloud.utils.db.GenericDaoBase;
public class ManagementServerJoinDaoImpl extends GenericDaoBase<ManagementServerJoinVO, Long> implements ManagementServerJoinDao {
}

View File

@ -0,0 +1,173 @@
// 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.api.query.vo;
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.management.ManagementServerHost;
import org.apache.cloudstack.management.ManagementServerHost.State;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
/**
* The Value object for api response utility view for management server queries
*/
@Entity
@Table(name = "mshost_view")
public class ManagementServerJoinVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "uuid")
private String uuid;
@Column(name = "msid", updatable = true, nullable = false)
private long msid;
@Column(name = "runid", updatable = true, nullable = false)
private long runid;
@Column(name = "name", updatable = true, nullable = true)
private String name;
@Column(name = "state", updatable = true, nullable = false)
@Enumerated(value = EnumType.STRING)
private ManagementServerHost.State state;
@Column(name = "version", updatable = true, nullable = true)
private String version;
@Column(name = "service_ip", updatable = true, nullable = false)
private String serviceIP;
@Column(name = "service_port", updatable = true, nullable = false)
private int servicePort;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "last_update", updatable = true, nullable = true)
private Date lastUpdateTime;
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
@Column(name = "alert_count", updatable = true, nullable = false)
private int alertCount;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="last_jvm_start")
private Date lastJvmStart;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="last_jvm_stop")
private Date lastJvmStop;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="last_system_boot")
private Date lastSystemBoot;
@Column(name="os_distribution")
private String osDistribution;
@Column(name="java_name")
private String javaName;
@Column(name="java_version")
private String javaVersion;
public long getId() {
return id;
}
public String getUuid() {
return uuid;
}
public long getMsid() {
return msid;
}
public long getRunid() {
return runid;
}
public String getName() {
return name;
}
public State getState() {
return state;
}
public String getVersion() {
return version;
}
public String getServiceIP() {
return serviceIP;
}
public int getServicePort() {
return servicePort;
}
public Date getLastUpdateTime() {
return lastUpdateTime;
}
public Date getRemoved() {
return removed;
}
public int getAlertCount() {
return alertCount;
}
public Date getLastJvmStart() {
return lastJvmStart;
}
public Date getLastJvmStop() {
return lastJvmStop;
}
public Date getLastSystemBoot() {
return lastSystemBoot;
}
public String getOsDistribution() {
return osDistribution;
}
public String getJavaName() {
return javaName;
}
public String getJavaVersion() {
return javaVersion;
}
}

View File

@ -0,0 +1,31 @@
// 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.server;
public interface DbStatsCollection {
String queries = "Queries";
String uptime = "Uptime";
String loadAvarages = "loadAverages";
String status = "STATUS";
String variables = "VARIABLES";
String connections = "Connections";
String currentTlsVersion = "Current_tls_version";
String version = "version";
String versionComment = "version_comment";
String collectionTime = "collectiontime";
}

View File

@ -0,0 +1,456 @@
//
// 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.server;
import java.util.Date;
public class ManagementServerHostStatsEntry implements ManagementServerHostStats {
private long managementServerHostId;
private String managementServerHostUuid;
private Date collectionTime;
private long sessions;
private double cpuUtilization;
private long totalJvmMemoryBytes;
private long freeJvmMemoryBytes;
private long maxJvmMemoryBytes;
private long processJvmMemoryBytes;
private long jvmUptime;
private long jvmStartTime;
private int availableProcessors;
private double loadAverage;
long totalInit;
long totalUsed;
long totalCommitted;
private long pid;
private String jvmName;
private String jvmVendor;
private String jvmVersion;
private String osDistribution;
private int agentCount;
private long heapMemoryUsed;
private long heapMemoryTotal;
private int threadsBlockedCount;
private int threadsDaemonCount;
private int threadsRunnableCount;
private int threadsTerminatedCount;
private int threadsTotalCount;
private int threadsWaitingCount;
private long systemMemoryTotal;
private long systemMemoryFree;
private long systemMemoryUsed;
private long systemMemoryVirtualSize;
private String logInfo;
private double systemTotalCpuCycles;
private double[] systemLoadAverages;
private long[] systemCyclesUsage;
private boolean dbLocal;
private boolean usageLocal;
private Date systemBootTime;
private String kernelVersion;
public ManagementServerHostStatsEntry() {
this(new Date());
}
public ManagementServerHostStatsEntry(Date date) {
collectionTime = date;
}
@Override
public long getManagementServerHostId() {
return managementServerHostId;
}
public void setManagementServerHostId(long managementServerHostId) {
this.managementServerHostId = managementServerHostId;
}
@Override
public String getManagementServerHostUuid() {
return managementServerHostUuid;
}
public void setManagementServerHostUuid(String managementServerHostUuid) {
this.managementServerHostUuid = managementServerHostUuid;
}
@Override
public Date getCollectionTime(){
return collectionTime;
}
@Override
public long getSessions() {
return sessions;
}
@Override
public double getCpuUtilization() {
return cpuUtilization;
}
@Override
public long getTotalJvmMemoryBytes() {
return totalJvmMemoryBytes;
}
@Override
public double getFreeJvmMemoryBytes() {
return freeJvmMemoryBytes;
}
@Override
public long getProcessJvmMemoryBytes() {
return processJvmMemoryBytes;
}
@Override
public long getJvmUptime() {
return jvmUptime;
}
@Override
public long getJvmStartTime() {
return jvmStartTime;
}
@Override
public int getAvailableProcessors() {
return availableProcessors;
}
@Override
public double getLoadAverage() {
return loadAverage;
}
@Override
public long getTotalInit() {
return totalInit;
}
@Override
public long getTotalUsed() {
return totalUsed;
}
@Override
public long getMaxJvmMemoryBytes() {
return maxJvmMemoryBytes;
}
@Override
public long getTotalCommitted() {
return totalCommitted;
}
@Override
public long getPid() {
return pid;
}
@Override
public String getJvmName() {
return jvmName;
}
@Override
public String getJvmVendor() {
return jvmVendor;
}
@Override
public String getJvmVersion() {
return jvmVersion;
}
@Override
public String getOsDistribution() {
return osDistribution;
}
@Override
public int getAgentCount() {
return agentCount;
}
@Override
public long getHeapMemoryUsed() {
return heapMemoryUsed;
}
@Override
public long getHeapMemoryTotal() {
return heapMemoryTotal;
}
public void setSessions(long sessions) {
this.sessions = sessions;
}
public void setCpuUtilization(double cpuUtilization) {
this.cpuUtilization = cpuUtilization;
}
public void setTotalJvmMemoryBytes(long totalJvmMemoryBytes) {
this.totalJvmMemoryBytes = totalJvmMemoryBytes;
}
public void setFreeJvmMemoryBytes(long freeJvmMemoryBytes) {
this.freeJvmMemoryBytes = freeJvmMemoryBytes;
}
public void setProcessJvmMemoryBytes(long processJvmMemoryBytes) {
this.processJvmMemoryBytes = processJvmMemoryBytes;
}
protected void validateSome() {
assert totalJvmMemoryBytes - processJvmMemoryBytes > freeJvmMemoryBytes;
}
public void setJvmUptime(long jvmUptime) {
this.jvmUptime = jvmUptime;
}
public void setJvmStartTime(long jvmStartTime) {
this.jvmStartTime = jvmStartTime;
}
public void setAvailableProcessors(int availableProcessors) {
this.availableProcessors = availableProcessors;
}
public void setLoadAverage(double loadAverage) {
this.loadAverage = loadAverage;
}
public void setTotalInit(long totalInit) {
this.totalInit = totalInit;
}
public void setTotalUsed(long totalUsed) {
this.totalUsed = totalUsed;
}
public void setMaxJvmMemoryBytes(long maxJvmMemoryBytes) {
this.maxJvmMemoryBytes = maxJvmMemoryBytes;
}
public void setTotalCommitted(long totalCommitted) {
this.totalCommitted = totalCommitted;
}
public void setProcessId(long pid) {
this.pid = pid;
}
public void setJvmName(String name) {
this.jvmName = name;
}
public void setJvmVendor(String vmVendor) {
this.jvmVendor = vmVendor;
}
public void setJvmVersion(String vmVersion) {
this.jvmVersion = vmVersion;
}
public void setOsDistribution(String osDistribution) {
this.osDistribution = osDistribution;
}
public void setAgentCount(int agentCount) {
this.agentCount = agentCount;
}
public void setHeapMemoryUsed(long heapMemoryUsed) {
this.heapMemoryUsed = heapMemoryUsed;
}
public void setHeapMemoryTotal(long heapMemoryTotal) {
this.heapMemoryTotal = heapMemoryTotal;
}
public void setThreadsBlockedCount(int threadsBlockedCount) {
this.threadsBlockedCount = threadsBlockedCount;
}
@Override
public int getThreadsBlockedCount() {
return threadsBlockedCount;
}
public void setThreadsTotalCount(int threadsTotalCount) {
this.threadsTotalCount = threadsTotalCount;
}
@Override
public int getThreadsTotalCount() {
return threadsTotalCount;
}
public void setThreadsDaemonCount(int threadsDaemonCount) {
this.threadsDaemonCount = threadsDaemonCount;
}
@Override
public int getThreadsDaemonCount() {
return threadsDaemonCount;
}
public void setThreadsRunnableCount(int threadsRunnableCount) {
this.threadsRunnableCount = threadsRunnableCount;
}
@Override
public int getThreadsRunnableCount() {
return threadsRunnableCount;
}
public void setThreadsTerminatedCount(int threadsTerminatedCount) {
this.threadsTerminatedCount = threadsTerminatedCount;
}
@Override
public int getThreadsTerminatedCount() {
return threadsTerminatedCount;
}
public void setThreadsWaitingCount(int threadsWaitingCount) {
this.threadsWaitingCount = threadsWaitingCount;
}
@Override
public int getThreadsWaitingCount() {
return threadsWaitingCount;
}
public void setSystemMemoryTotal(long systemMemoryTotal) {
this.systemMemoryTotal = systemMemoryTotal;
}
@Override
public long getSystemMemoryTotal() {
return systemMemoryTotal;
}
public void setSystemMemoryFree(long systemMemoryFree) {
this.systemMemoryFree = systemMemoryFree;
}
@Override
public long getSystemMemoryFree() {
return systemMemoryFree;
}
public void setSystemMemoryUsed(long systemMemoryUsed) {
this.systemMemoryUsed = systemMemoryUsed;
}
@Override
public long getSystemMemoryUsed() {
return systemMemoryUsed;
}
public void setSystemMemoryVirtualSize(long systemMemoryVirtualSize) {
this.systemMemoryVirtualSize = systemMemoryVirtualSize;
}
@Override
public long getSystemMemoryVirtualSize() {
return systemMemoryVirtualSize;
}
public void setLogInfo(String logInfo) {
this.logInfo = logInfo;
}
@Override
public String getLogInfo() {
return logInfo;
}
public void setSystemTotalCpuCycles(double systemTotalCpuCycles) {
this.systemTotalCpuCycles = systemTotalCpuCycles;
}
@Override
public double getSystemTotalCpuCycles() {
return systemTotalCpuCycles;
}
public void setSystemLoadAverages(double[] systemLoadAverages) {
this.systemLoadAverages = systemLoadAverages;
}
@Override
public double[] getSystemLoadAverages() {
return systemLoadAverages;
}
public void setSystemCyclesUsage(long[] systemCyclesUsage) {
this.systemCyclesUsage = systemCyclesUsage;
}
@Override
public long[] getSystemCyclesUsage() {
return systemCyclesUsage;
}
public void setDbLocal(boolean dbLocal) {
this.dbLocal = dbLocal;
}
@Override
public boolean isDbLocal() {
return dbLocal;
}
public void setUsageLocal(boolean usageLocal) {
this.usageLocal = usageLocal;
}
@Override
public boolean isUsageLocal() {
return usageLocal;
}
@Override
public Date getSystemBootTime() {
return systemBootTime;
}
public void setSystemBootTime(Date systemBootTime) {
this.systemBootTime = systemBootTime;
}
public void setKernelVersion(String kernelVersion) {
this.kernelVersion = kernelVersion;
}
@Override
public String getKernelVersion() {
return kernelVersion;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -85,6 +85,7 @@
<dao name="Console Proxy" class="com.cloud.vm.dao.ConsoleProxyDaoImpl" />
<dao name="Upgrade" class="com.cloud.maint.dao.AgentUpgradeDaoImpl" />
<dao name="Management Server Host" class="com.cloud.cluster.dao.ManagementServerHostDaoImpl" />
<dao name="Management Server Status" class="com.cloud.cluster.dao.ManagementServerStatusDaoImpl" />
<dao name="Snapshot" class="com.cloud.storage.dao.SnapshotDaoImpl" />
<dao name="ScheduledVMBackup" class="com.cloud.user.dao.ScheduledVMBackupDaoImpl" />
<dao name="AsyncJobDao" class="com.cloud.async.dao.AsyncJobDaoImpl" />

View File

@ -20,13 +20,14 @@ package com.cloud.server;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.Properties;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.influxdb.InfluxDB;
@ -58,6 +59,8 @@ import com.cloud.vm.dao.VmStatsDao;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(DataProviderRunner.class)
@PrepareForTest({InfluxDBFactory.class, BatchPoints.class})
@ -108,7 +111,7 @@ public class StatsCollectorTest {
statsCollector.externalStatsHost = HOST_ADDRESS;
statsCollector.externalStatsPort = INFLUXDB_DEFAULT_PORT;
InfluxDB influxDbConnection = Mockito.mock(InfluxDB.class);
Mockito.when(influxDbConnection.databaseExists(DEFAULT_DATABASE_NAME)).thenReturn(databaseExists);
when(influxDbConnection.databaseExists(DEFAULT_DATABASE_NAME)).thenReturn(databaseExists);
PowerMockito.mockStatic(InfluxDBFactory.class);
PowerMockito.when(InfluxDBFactory.connect(URL)).thenReturn(influxDbConnection);
@ -125,7 +128,7 @@ public class StatsCollectorTest {
BatchPoints batchPoints = Mockito.mock(BatchPoints.class);
PowerMockito.mockStatic(BatchPoints.class);
PowerMockito.when(BatchPoints.database(DEFAULT_DATABASE_NAME)).thenReturn(builder);
Mockito.when(builder.build()).thenReturn(batchPoints);
when(builder.build()).thenReturn(batchPoints);
Map<String, String> tagsToAdd = new HashMap<>();
tagsToAdd.put("hostId", "1");
Map<String, Object> fieldsToAdd = new HashMap<>();
@ -133,7 +136,7 @@ public class StatsCollectorTest {
Point point = Point.measurement("measure").tag(tagsToAdd).time(System.currentTimeMillis(), TimeUnit.MILLISECONDS).fields(fieldsToAdd).build();
List<Point> points = new ArrayList<>();
points.add(point);
Mockito.when(batchPoints.point(point)).thenReturn(batchPoints);
when(batchPoints.point(point)).thenReturn(batchPoints);
statsCollector.writeBatches(influxDbConnection, DEFAULT_DATABASE_NAME, points);
@ -376,4 +379,46 @@ public class StatsCollectorTest {
Assert.assertEquals(6.2, result.getDiskWriteIOs(), 0);
}
@Test
public void testIsDbIpv6Local() {
Properties p = new Properties();
p.put("db.cloud.host", "::1");
when(statsCollector.getDbProperties()).thenReturn(p);
Assert.assertTrue(statsCollector.isDbLocal());
}
@Test
public void testIsDbIpv4Local() {
Properties p = new Properties();
p.put("db.cloud.host", "127.0.0.1");
when(statsCollector.getDbProperties()).thenReturn(p);
Assert.assertTrue(statsCollector.isDbLocal());
}
@Test
public void testIsDbSymbolicLocal() {
Properties p = new Properties();
p.put("db.cloud.host", "localhost");
when(statsCollector.getDbProperties()).thenReturn(p);
Assert.assertTrue(statsCollector.isDbLocal());
}
@Test
public void testIsDbOnSameIp() {
Properties p = new Properties();
p.put("db.cloud.host", "10.10.10.10");
p.put("cluster.node.IP", "10.10.10.10");
when(statsCollector.getDbProperties()).thenReturn(p);
Assert.assertTrue(statsCollector.isDbLocal());
}
@Test
public void testIsDbNotLocal() {
Properties p = new Properties();
p.put("db.cloud.host", "10.10.10.11");
p.put("cluster.node.IP", "10.10.10.10");
when(statsCollector.getDbProperties()).thenReturn(p);
Assert.assertFalse(statsCollector.isDbLocal());
}
}

View File

@ -30,42 +30,44 @@ _multiprocess_shared_ = True
class TestMetrics(cloudstackTestCase):
def setUp(self):
self.apiclient = self.testClient.getApiClient()
self.hypervisor = self.testClient.getHypervisorInfo()
self.dbclient = self.testClient.getDbConnection()
self.services = self.testClient.getParsedTestDataConfig()
self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests())
self.pod = get_pod(self.apiclient, self.zone.id)
self.host = list_hosts(self.apiclient,
zoneid=self.zone.id,
type='Routing')[0]
self.cluster = self.apiclient.listClusters(listClusters.listClustersCmd())[0]
self.disk_offering = DiskOffering.create(
self.apiclient,
self.services["disk_offering"]
)
self.service_offering = ServiceOffering.create(
self.apiclient,
self.services["service_offering"]
@classmethod
def setUpClass(cls):
cls.apiclient = cls.testClient.getApiClient()
cls.hypervisor = cls.testClient.getHypervisorInfo()
cls.dbclient = cls.testClient.getDbConnection()
cls.services = cls.testClient.getParsedTestDataConfig()
cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
cls.pod = get_pod(cls.apiclient, cls.zone.id)
cls.host = list_hosts(cls.apiclient,
zoneid=cls.zone.id,
type='Routing')[0]
cls.cluster = cls.apiclient.listClusters(listClusters.listClustersCmd())[0]
cls._cleanup = []
cls.disk_offering = DiskOffering.create(
cls.apiclient,
cls.services["disk_offering"]
)
self.template = get_test_template(
self.apiclient,
self.zone.id,
self.hypervisor
cls._cleanup.append(cls.disk_offering)
cls.service_offering = ServiceOffering.create(
cls.apiclient,
cls.services["service_offering"]
)
cls.template = get_test_template(
cls.apiclient,
cls.zone.id,
cls.hypervisor
)
cls._cleanup.append(cls.service_offering)
@classmethod
def tearDownClass(cls):
super(TestMetrics, cls).tearDownClass()
def setUp(self):
self.cleanup = []
self.cleanup.append(self.disk_offering)
self.cleanup.append(self.service_offering)
def tearDown(self):
try:
#Clean up
cleanup_resources(self.apiclient, self.cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
super(TestMetrics, self).tearDown();
@attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false")
def test_list_hosts_metrics(self):
@ -79,6 +81,8 @@ class TestMetrics(cloudstackTestCase):
self.assertEqual(host_metric.cpuallocated, self.host.cpuallocated)
self.assertEqual(host_metric.memoryallocated, self.host.memoryallocated)
return
@attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false")
def test_list_clusters_metrics(self):
@ -94,6 +98,8 @@ class TestMetrics(cloudstackTestCase):
self.assertTrue(hasattr(cluster_metric, 'memoryused'))
self.assertTrue(hasattr(cluster_metric, 'memorymaxdeviation'))
return
@attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false")
def test_list_zones_metrics(self):
cmd = listZonesMetrics.listZonesMetricsCmd()
@ -109,6 +115,8 @@ class TestMetrics(cloudstackTestCase):
self.assertTrue(hasattr(zone_metrics, 'memorymaxdeviation'))
self.assertTrue(hasattr(zone_metrics, 'memoryused'))
return
@attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false")
def test_list_vms_metrics(self):
#deploy VM
@ -152,6 +160,8 @@ class TestMetrics(cloudstackTestCase):
self.assertEqual(sp_metrics.disksizeallocated, sp.disksizeallocated)
self.assertEqual(sp_metrics.state, sp.state)
return
@attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false")
def test_list_volumes_metrics(self):
volume = Volume.create(
@ -208,3 +218,162 @@ class TestMetrics(cloudstackTestCase):
self.assertTrue(hasattr(li, 'systemvms'))
self.assertTrue(hasattr(li, 'cpusockets'))
return
@attr(tags = ["advanced", "advancedns", "smoke", "basic", "bla"], required_hardware="false")
def test_list_management_server_metrics(self):
cmd = listManagementServersMetrics.listManagementServersMetricsCmd()
listMSMs = self.apiclient.listManagementServersMetrics(cmd)
cmd = listManagementServers.listManagementServersCmd()
listMSs= self.apiclient.listManagementServers(cmd)
self.assertEqual(len(listMSMs), len(listMSs))
metrics = listMSMs[0]
self.assertTrue(hasattr(metrics, 'availableprocessors'))
self.assertTrue(isinstance(metrics.availableprocessors, int))
self.assertTrue(hasattr(metrics, 'agentcount'))
self.assertTrue(isinstance(metrics.agentcount, int))
self.assertTrue(hasattr(metrics, 'sessions'))
self.assertTrue(isinstance(metrics.sessions, int))
self.assertTrue(hasattr(metrics, 'heapmemoryused'))
self.assertTrue(isinstance(metrics.heapmemoryused, int))
self.assertTrue(hasattr(metrics, 'heapmemorytotal'))
self.assertTrue(isinstance(metrics.heapmemorytotal, int))
self.assertTrue(metrics.heapmemoryused <= metrics.heapmemorytotal)
self.assertTrue(hasattr(metrics, 'threadsblockedcount'))
self.assertTrue(isinstance(metrics.threadsblockedcount, int))
self.assertTrue(hasattr(metrics, 'threadsdaemoncount'))
self.assertTrue(isinstance(metrics.threadsdaemoncount, int))
self.assertTrue(hasattr(metrics, 'threadsrunnablecount'))
self.assertTrue(isinstance(metrics.threadsrunnablecount, int))
self.assertTrue(hasattr(metrics, 'threadsteminatedcount'))
self.assertTrue(isinstance(metrics.threadsteminatedcount, int))
self.assertTrue(hasattr(metrics, 'threadstotalcount'))
self.assertTrue(isinstance(metrics.threadstotalcount, int))
self.assertTrue(hasattr(metrics, 'threadswaitingcount'))
self.assertTrue(isinstance(metrics.threadswaitingcount, int))
self.assertTrue(metrics.threadsblockedcount <= metrics.threadstotalcount)
self.assertTrue(metrics.threadsdaemoncount <= metrics.threadstotalcount)
self.assertTrue(metrics.threadsrunnablecount <= metrics.threadstotalcount)
self.assertTrue(metrics.threadsteminatedcount <= metrics.threadstotalcount)
self.assertTrue(metrics.threadswaitingcount <= metrics.threadstotalcount)
self.assertTrue(hasattr(metrics, 'systemmemorytotal'))
self.assertTrue(isinstance(metrics.systemmemorytotal, str))
self.assertTrue(hasattr(metrics, 'systemmemoryfree'))
self.assertTrue(isinstance(metrics.systemmemoryfree, str))
self.assertTrue(hasattr(metrics, 'systemmemoryvirtualsize'))
self.assertTrue(isinstance(metrics.systemmemoryvirtualsize, str))
self.assertTrue(hasattr(metrics, 'loginfo'))
self.assertTrue(isinstance(metrics.loginfo, str))
self.assertTrue(hasattr(metrics, 'systemtotalcpucycles'))
self.assertTrue(isinstance(metrics.systemtotalcpucycles, float))
self.assertTrue(hasattr(metrics, 'systemloadaverages'))
self.assertTrue(isinstance(metrics.systemloadaverages, list))
self.assertEqual(len(metrics.systemloadaverages), 3)
self.assertTrue(hasattr(metrics, 'systemcycleusage'))
self.assertTrue(isinstance(metrics.systemcycleusage, list))
self.assertEqual(len(metrics.systemcycleusage), 3)
self.assertTrue(hasattr(metrics, 'dbislocal'))
self.assertTrue(isinstance(metrics.dbislocal, bool))
self.assertTrue(hasattr(metrics, 'usageislocal'))
self.assertTrue(isinstance(metrics.usageislocal, bool))
self.assertTrue(hasattr(metrics, 'collectiontime'))
self.assertTrue(isinstance(metrics.collectiontime, str))
self.assertTrue(self.valid_date(metrics.collectiontime))
self.assertTrue(hasattr(metrics, 'id'))
self.assertTrue(isinstance(metrics.id, str))
self.assertTrue(hasattr(metrics, 'name'))
self.assertTrue(isinstance(metrics.name, str))
self.assertTrue(hasattr(metrics, 'state'))
self.assertEqual(metrics.state, 'Up')
self.assertTrue(hasattr(metrics, 'version'))
self.assertTrue(isinstance(metrics.version, str))
self.assertTrue(hasattr(metrics, 'javadistribution'))
self.assertTrue(isinstance(metrics.javadistribution, str))
self.assertTrue(hasattr(metrics, 'javaversion'))
self.assertTrue(isinstance(metrics.javaversion, str))
self.assertTrue(hasattr(metrics, 'osdistribution'))
self.assertTrue(isinstance(metrics.osdistribution, str))
self.assertTrue(hasattr(metrics, 'lastserverstart'))
self.assertTrue(isinstance(metrics.lastserverstart, str))
self.assertTrue(self.valid_date(metrics.lastserverstart))
if hasattr(metrics, 'lastserverstop') and metrics.lastserverstop:
self.debug(f"=== lastserverstop {metrics.lastserverstop} ===")
self.assertTrue(isinstance(metrics.lastserverstop, str))
self.assertTrue(self.valid_date(metrics.lastserverstop))
self.assertTrue(hasattr(metrics, 'lastboottime'))
self.assertTrue(isinstance(metrics.lastboottime, str))
self.assertTrue(self.valid_date(metrics.lastboottime))
return
@attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false")
def test_list_usage_server_metrics(self):
cmd = listUsageServerMetrics.listUsageServerMetricsCmd()
metrics = self.apiclient.listUsageServerMetrics(cmd)
self.assertTrue(hasattr(metrics,'collectiontime'))
self.assertTrue(isinstance(metrics.collectiontime, str))
self.assertTrue(self.valid_date(metrics.collectiontime))
self.assertTrue(hasattr(metrics, 'hostname'))
self.assertTrue(isinstance(metrics.hostname, str))
if hasattr(metrics, 'lastheartbeat') and metrics.lastheartbeat :
self.debug(f"=== lastheartbeat {metrics.lastheartbeat} ===")
self.assertTrue(isinstance(metrics.lastheartbeat, str))
self.assertTrue(self.valid_date(metrics.lastheartbeat))
if hasattr(metrics, 'lastsuccessfuljob') and metrics.lastsuccessfuljob:
self.debug(f"=== lastsuccessfuljob {metrics.lastsuccessfuljob} ===")
self.assertTrue(isinstance(metrics.lastsuccessfuljob, str))
self.assertTrue(self.valid_date(metrics.lastsuccessfuljob))
self.assertTrue(hasattr(metrics, 'state'))
self.assertTrue(metrics.state == 'Up' or metrics.state == 'Down')
return
@attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false")
def test_list_db_metrics(self):
cmd = listDbMetrics.listDbMetricsCmd()
metrics = self.apiclient.listDbMetrics(cmd)
self.assertTrue(hasattr(metrics,'collectiontime'))
self.assertTrue(isinstance(metrics.collectiontime, str))
self.assertTrue(self.valid_date(metrics.collectiontime))
self.assertTrue(hasattr(metrics, 'connections'))
self.assertTrue(isinstance(metrics.connections, int))
cmd = listConfigurations.listConfigurationsCmd()
cmd.name = 'database.server.stats.retention'
configuration = self.apiclient.listConfigurations(cmd)
retention = int(configuration[0].value)
self.assertTrue(hasattr(metrics, 'dbloadaverages'))
self.assertTrue(isinstance(metrics.dbloadaverages, list))
self.assertTrue(len(metrics.dbloadaverages) <= retention)
self.assertTrue(hasattr(metrics, 'hostname'))
self.assertTrue(isinstance(metrics.hostname, str))
self.assertTrue(hasattr(metrics, 'queries'))
self.assertTrue(isinstance(metrics.queries, int))
self.assertTrue(hasattr(metrics, 'replicas'))
self.assertTrue(isinstance(metrics.replicas, list))
self.assertTrue(hasattr(metrics, 'uptime'))
self.assertTrue(isinstance(metrics.uptime, int))
self.assertTrue(hasattr(metrics, 'version'))
self.assertTrue(isinstance(metrics.version, str))
self.assertTrue(hasattr(metrics, 'versioncomment'))
self.assertTrue(isinstance(metrics.versioncomment, str))
return
def valid_date(cls, date_text):
try:
datetime.datetime.strptime(date_text, '%Y-%m-%dT%H:%M:%S%z')
return True
except ValueError:
return False

32845
ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1823,7 +1823,6 @@
"label.rolename" : "Ρόλο",
"label.roles" : "Ρόλους",
"label.roletype" : "Τύπος ρόλου",
"label.rootdisksize" : "Μέγεθος ριζικού δίσκου (GB)",
"label.root.certificate" : "Πιστοποιητικό ρίζας",
"label.root.disk.offering" : "Προσφορά ριζικού δίσκου",
"label.root.disk.size" : "Μέγεθος ριζικού δίσκου (GB)",

View File

@ -431,6 +431,7 @@
"label.affinity": "Affinity",
"label.affinity.groups": "Affinity Groups",
"label.affinitygroup": "Affinity Group",
"label.agentcount": "Number Of Connected Agents",
"label.agent.password": "Agent Password",
"label.agent.username": "Agent Username",
"label.agentport": "Agent Port",
@ -492,6 +493,7 @@
"label.availability": "Availability",
"label.availabilityzone": "Availability Zone",
"label.available": "Available",
"label.availableprocessors": "Available Processor Cores",
"label.available.public.ips": "Available Public IP Addresses",
"label.back": "Back",
"label.backup": "Backups",
@ -607,6 +609,7 @@
"label.clustertype": "Cluster Type",
"label.clvm": "CLVM",
"label.code": "Code",
"label.collectiontime": "Collection time",
"label.columns": "Columns",
"label.comma.separated.list.description": "Enter comma-separated list of commands",
"label.comments": "Comments",
@ -658,6 +661,7 @@
"label.cpuallocated": "CPU Allocated for VMs",
"label.cpuallocatedghz": "CPU Allocated",
"label.cpulimit": "CPU limits",
"label.cpuload": "% CPU in use",
"label.cpumaxdeviation": "Deviation",
"label.cpunumber": "CPU Cores",
"label.cpusockets": "The Number of CPU Sockets",
@ -711,6 +715,8 @@
"label.day": "Day",
"label.day.of.month": "Day of Month",
"label.day.of.week": "Day of Week",
"label.db.usage.metrics": "DB/Usage Server",
"label.dbislocal": "The db runs locally",
"label.dc.name": "DC Name",
"label.decline.invitation": "Decline invitation",
"label.dedicate": "Dedicate",
@ -778,7 +784,9 @@
"label.deny": "Deny",
"label.deployasis":"Read VM settings from OVA",
"label.deploymentplanner": "Deployment planner",
"label.desc.db.stats": "Database Statistics",
"label.desc.importexportinstancewizard": "Import and export instances to/from an existing VMware cluster.",
"label.desc.usage.stats": "Usage Server Statistics",
"label.description": "Description",
"label.destcidr": "Destination CIDR",
"label.destination": "Destination",
@ -1074,6 +1082,8 @@
"label.health.check.message.desc": "Your load balancer will automatically perform health checks on your cloudstack instances and only route traffic to instances that pass the health check",
"label.health.check.wizard": "Health Check Wizard",
"label.healthy.threshold": "Healthy Threshold",
"label.heapmemoryused": "Heap-memory used",
"label.heapmemorytotal": "Heap-memory available",
"label.help": "Help",
"label.hide.ingress.rule": "Hide Ingress Rule",
"label.hideipaddressusage": "Hide IP Address Usage",
@ -1247,8 +1257,11 @@
"label.items": "items",
"label.items.selected": "item(s) selected",
"label.japanese.keyboard": "Japanese keyboard",
"label.javadistribution": "Java Runtime Distribution",
"label.javaversion": "Java Runtime Version",
"label.keep": "Keep",
"label.keep.colon": "Keep:",
"label.kernelversion": "Kernel Version",
"label.key": "Key",
"label.keyboard": "Keyboard language",
"label.keyboardtype": "Keyboard type",
@ -1297,8 +1310,11 @@
"label.lang.spanish": "Spanish",
"label.last.updated": "Last Update",
"label.lastannotated": "Last annotation date",
"label.lastboottime": "Boot time of the management server machine",
"label.lastname": "Last Name",
"label.lastname.lower": "lastname",
"label.lastserverstart": "Last Management Server start time",
"label.lastserverstop": "Last stop time for this management server",
"label.latest.events": "Latest events",
"label.launch": "Launch",
"label.launch.vm": "Launch Instance",
@ -1346,6 +1362,7 @@
"label.localstorageenabled": "Enable local storage for User VMs",
"label.localstorageenabledforsystemvm": "Enable local storage for System VMs",
"label.login": "Login",
"label.loginfo": "Log File Information",
"label.login.portal": "Portal Login",
"label.login.single.signon": "Single Sign-On",
"label.logout": "Logout",
@ -1619,6 +1636,7 @@
"label.order": "Order",
"label.oscategoryid": "OS Preference",
"label.ostypeid": "OS Type",
"label.osdistribution": "OS Distribution",
"label.ostypename": "OS Type",
"label.other": "Other",
"label.outofbandmanagement": "Out-of-band Management",
@ -1933,7 +1951,6 @@
"label.rootdisk": "ROOT disk",
"label.rootdiskcontrollertype": "Root disk controller",
"label.rootdiskcontrollertypekvm": "Root disk controller",
"label.rootdisksize": "Root disk size (GB)",
"label.router.health.check.last.updated": "Last updated",
"label.router.health.check.name": "Check name",
"label.router.health.check.success": "Success",
@ -2047,6 +2064,7 @@
"label.serviceofferingid": "Compute Offering",
"label.serviceofferingname": "Compute Offering",
"label.session.expired": "Session Expired",
"label.sessions": "Active Client Sessions",
"label.set.default.nic": "Set default NIC",
"label.set.reservation": "Set Reservation",
"label.set.reservation.desc": "(optional) Please specify an account to be associated with this IP range.<br/><br/>System VMs: Enable dedication of public IP range for SSVM and CPVM, account field disabled. Reservation strictness defined on 'system.vm.public.ip.reservation.mode.strictness'",
@ -2200,6 +2218,13 @@
"label.system.vm.scaled.up": "System VM Scaled Up",
"label.system.vms": "System VMs",
"label.system.wide.capacity": "System-wide capacity",
"label.systemcycleusage": "User, System and Idle Cycles",
"label.systemloadaverages": "1, 5 and 15 minute load averages",
"label.systemmemoryfree": "Free System Memory",
"label.systemmemorytotal": "Total System Memory",
"label.systemmemoryused": "Used System Memory",
"label.systemmemoryvirtualsize": "Virtual Total Process Size",
"label.systemtotalcpucycles": "Total CPU capacity for all cores in MHz",
"label.systemvmtype": "System VM Type",
"label.tag.key": "Tag Key",
"label.tag.value": "Tag Value",
@ -2252,6 +2277,13 @@
"label.theme.sunset.orange": "Sunset Orange",
"label.theme.volcano": "Volcano",
"label.theme.white": "White",
"label.threadsblockedcount": "Blocked Threads",
"label.threadsdeamoncount": "Deamon Threads",
"label.threadsnewcount": "New Threads",
"label.threadsrunnablecount": "Runnable Threads",
"label.threadsterminatedcount": "Terminated Threads",
"label.threadstotalcount": "Total Thread count",
"label.threadswaitingcount": "Waiting Threads",
"label.threshold": "Threshold",
"label.thursday": "Thursday",
"label.tier.details": "Tier details",
@ -2321,9 +2353,11 @@
"label.url": "URL",
"label.usage.sanity.result": "Usage Sanity Result",
"label.usage.server": "Usage Server",
"label.usage.explanation": "Note: Only the usage server that owns the active usage job is shown here.",
"label.usageinterface": "Usage Interface",
"label.usagename": "Usage Type",
"label.usageunit": "Unit",
"label.usageislocal": "A Usage Server is installed locally",
"label.use.kubectl.access.cluster": "<code><b>kubectl</b></code> and <code><b>kubeconfig</b></code> file to access cluster",
"label.use.local.timezone": "Use Local Timezone",
"label.use.vm.ip": "Use VM IP:",

View File

@ -43,7 +43,7 @@
<span v-if="['USER.LOGIN', 'USER.LOGOUT', 'ROUTER.HEALTH.CHECKS', 'FIREWALL.CLOSE', 'ALERT.SERVICE.DOMAINROUTER'].includes(dataResource[item])">{{ $t(dataResource[item].toLowerCase()) }}</span>
<span v-else>{{ dataResource[item] }}</span>
</div>
<div v-else-if="['created', 'sent', 'lastannotated'].includes(item)">
<div v-else-if="['created', 'sent', 'lastannotated', 'collectiontime', 'lastboottime', 'lastserverstart', 'lastserverstop'].includes(item)">
{{ $toLocaleDate(dataResource[item]) }}
</div>
<div v-else-if="$route.meta.name === 'guestnetwork' && item === 'egressdefaultpolicy'">

View File

@ -26,6 +26,7 @@ import secondaryStorages from '@/config/section/infra/secondaryStorages'
import systemVms from '@/config/section/infra/systemVms'
import routers from '@/config/section/infra/routers'
import ilbvms from '@/config/section/infra/ilbvms'
import managementServers from '@/config/section/infra/managementServers'
export default {
name: 'infra',
@ -51,6 +52,7 @@ export default {
systemVms,
routers,
ilbvms,
managementServers,
{
name: 'cpusocket',
title: 'label.cpu.sockets',
@ -60,11 +62,12 @@ export default {
component: () => import('@/views/infra/CpuSockets.vue')
},
{
name: 'managementserver',
title: 'label.management.servers',
icon: 'RocketOutlined',
permission: ['listManagementServers'],
columns: ['name', 'state', 'version']
name: 'metric',
title: 'label.db.usage.metrics',
icon: 'bar-chart-outlined',
docHelp: 'adminguide/management.html#metrics',
permission: ['listDbMetrics', 'listUsageServerMetrics'],
component: () => import('@/views/infra/Metrics.vue')
},
{
name: 'alert',

View File

@ -0,0 +1,41 @@
// 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.
import store from '@/store'
import { shallowRef, defineAsyncComponent } from 'vue'
export default {
name: 'managementserver',
title: 'label.management.servers',
icon: 'CloudServerOutlined',
permission: ['listManagementServersMetrics'],
columns: () => {
const fields = ['name', 'state', 'version']
const metricsFields = ['collectiontime', 'availableprocessors', 'cpuload', 'systemmemoryused', 'heapmemoryused', 'agentcount']
if (store.getters.metrics) {
fields.push(...metricsFields)
}
return fields
},
details: ['collectiontime', 'usageislocal', 'dbislocal', 'lastserverstart', 'lastserverstop', 'lastboottime', 'version', 'loginfo', 'systemtotalcpucycles', 'systemloadaverages', 'systemcycleusage', 'systemmemorytotal', 'systemmemoryfree', 'systemmemoryused', 'systemmemoryvirtualsize', 'availableprocessors', 'javadistribution', 'javaversion', 'osdistribution', 'kernelversion', 'agentcount', 'sessions', 'heapmemoryused', 'heapmemorytotal', 'threadsblockedcount', 'threadsdeamoncount', 'threadsnewcount', 'threadsrunnablecount', 'threadsterminatedcount', 'threadstotalcount', 'threadswaitingcount'],
tabs: [
{
name: 'details',
component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue')))
}
]
}

View File

@ -24,6 +24,7 @@ import {
ArrowsAltOutlined,
AuditOutlined,
BankOutlined,
BarChartOutlined,
BarcodeOutlined,
BarsOutlined,
BellOutlined,
@ -48,10 +49,12 @@ import {
CloseOutlined,
CloudDownloadOutlined,
CloudOutlined,
CloudServerOutlined,
CloudUploadOutlined,
ClusterOutlined,
CodeOutlined,
CompassOutlined,
ControlOutlined,
CopyOutlined,
CreditCardOutlined,
DashboardOutlined,
@ -167,6 +170,7 @@ export default {
app.component('ArrowsAltOutlined', ArrowsAltOutlined)
app.component('AuditOutlined', AuditOutlined)
app.component('BankOutlined', BankOutlined)
app.component('BarChartOutlined', BarChartOutlined)
app.component('BarcodeOutlined', BarcodeOutlined)
app.component('BarsOutlined', BarsOutlined)
app.component('BellOutlined', BellOutlined)
@ -191,9 +195,11 @@ export default {
app.component('CloseOutlined', CloseOutlined)
app.component('CloudDownloadOutlined', CloudDownloadOutlined)
app.component('CloudOutlined', CloudOutlined)
app.component('CloudServerOutlined', CloudServerOutlined)
app.component('CloudUploadOutlined', CloudUploadOutlined)
app.component('ClusterOutlined', ClusterOutlined)
app.component('CodeOutlined', CodeOutlined)
app.component('ControlOutlined', ControlOutlined)
app.component('CompassOutlined', CompassOutlined)
app.component('CopyOutlined', CopyOutlined)
app.component('CreditCardOutlined', CreditCardOutlined)

View File

@ -33,7 +33,7 @@
{{ $t('label.refresh') }}
</a-button>
<a-switch
v-if="!dataView && ['vm', 'volume', 'zone', 'cluster', 'host', 'storagepool'].includes($route.name)"
v-if="!dataView && ['vm', 'volume', 'zone', 'cluster', 'host', 'storagepool', 'managementserver'].includes($route.name)"
style="margin-left: 8px"
:checked-children="$t('label.metrics')"
:un-checked-children="$t('label.metrics')"

View File

@ -185,7 +185,7 @@ export default {
return {
loading: true,
routes: {},
sections: ['zones', 'pods', 'clusters', 'hosts', 'storagepools', 'imagestores', 'systemvms', 'routers', 'cpusockets', 'managementservers', 'alerts', 'ilbvms'],
sections: ['zones', 'pods', 'clusters', 'hosts', 'storagepools', 'imagestores', 'systemvms', 'routers', 'cpusockets', 'managementservers', 'alerts', 'ilbvms', 'metrics'],
sslFormVisible: false,
stats: {},
intermediateCertificates: [],

View File

@ -0,0 +1,235 @@
// 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.
<template>
<div>
<a-card class="breadcrumb-card">
<breadcrumb>
<template #end>
<a-tooltip placement="bottom">
<template #title>{{ $t('label.refresh') }}</template>
<a-button
style="margin-top: 4px"
:loading="loading"
shape="round"
size="small"
icon="reload"
@click="fetchDetails()"
>{{ $t('label.refresh') }}</a-button>
</a-tooltip>
</template>
</breadcrumb>
</a-card>
<a-card>
<a-row :gutter="12">
<a-col :md="24" :lg="12" :gutter="12">
<a-card>
<template #title>
{{ $t('label.desc.db.stats') }}
</template>
<a-table
class="metric-card"
:columns="columns"
:loading="loading"
:data-source="dbMetrics"
:pagination="false"
size="middle"
:rowClassName="getRowClassName"
/>
</a-card>
</a-col>
<a-col :md="24" :lg="12" :gutter="12">
<a-card>
<template #title>
{{ $t('label.desc.usage.stats') }}
</template>
<a-table
class="metric-card"
:columns="columns"
:data-source="usageMetrics"
:pagination="false"
size="middle"
:rowClassName="getRowClassName"
/>
<div>
<p>{{ $t('label.usage.explanation') }}</p>
</div>
</a-card>
</a-col>
</a-row>
</a-card>
</div>
</template>
<script>
import { api } from '@/api'
import { genericCompare } from '@/utils/sort.js'
import Breadcrumb from '@/components/widgets/Breadcrumb'
export default {
name: 'Metrics',
components: {
Breadcrumb
},
props: {
loading: {
type: Boolean,
default: false
}
},
data () {
return {
dbMetrics: [],
usageMetrics: [],
columns: [
{
title: this.$t('label.name'),
dataIndex: 'name',
width: '30%'
},
{
title: this.$t('label.value'),
dataIndex: 'value'
}
]
}
},
mounted () {
this.fetchDetails()
},
watch: {
},
methods: {
fetchDbMetrics () {
var metrics
api('listDbMetrics').then(json => {
metrics = this.mapToArray(json.listdbmetricsresponse.dbMetrics)
this.dbMetrics = metrics
})
return metrics
},
fetchUsageMetrics () {
var metrics
api('listUsageServerMetrics').then(json => {
metrics = this.mapToArray(json.listusageservermetricsresponse.usageMetrics)
this.usageMetrics = metrics
})
return metrics
},
mapToArray (map) {
/* eslint-disable no-unused-vars */
var array = []
for (var key in map) {
if (key === 'replicas') {
// we don't display replica's at this stage as usually they are not used,
// only some people experimenting with galera use them.
} else if (key === 'dbloadaverages') {
map[key].forEach(function (value, i) {
var metric = {}
if (i === 0) {
metric.name = 'queries/second over the latest stats collection period'
} else {
metric.name = 'queries/seconds-' + (i + 1)
}
metric.value = value
array.push(metric)
})
} else if (key === 'connections') {
var metric = {}
metric.name = 'connection attempts since start'
metric.value = map[key]
array.push(metric)
} else if (key === 'uptime') {
metric = {}
metric.name = 'uptime in seconds'
metric.value = map[key]
array.push(metric)
} else if (key === 'collectiontime' || key === 'lastheartbeat' || key === 'lastsuccesfuljob') {
metric = {}
metric.name = key
metric.value = this.$toLocaleDate(map[key]) // needs a conversion
array.push(metric)
} else {
metric = {}
metric.name = key
metric.value = map[key]
array.push(metric)
}
}
/* eslint-enable no-unused-vars */
return array
},
fetchDetails () {
this.dbMetrics = this.fetchDbMetrics()
this.usageMetrics = this.fetchUsageMetrics()
},
fetchUsageListData () {
this.columns = []
this.columns.push({
dataIndex: 'name',
title: this.$t('label.name'),
sorter: function (a, b) { return genericCompare(a[this.dataIndex] || '', b[this.dataIndex] || '') }
})
this.columns.push({
dataIndex: 'value',
title: this.$t('label.value'),
sorter: function (a, b) { return genericCompare(a[this.dataIndex] || '', b[this.dataIndex] || '') }
})
},
getRowClassName (record, index) {
if (index % 2 === 0) {
return 'light-row'
}
return 'dark-row'
}
}
}
</script>
<style scoped lang="less">
.breadcrumb-card {
margin-left: -24px;
margin-right: -24px;
margin-top: -18px;
margin-bottom: 12px;
}
/deep/ .ant-table-thead {
background-color: #f9f9f9;
}
/deep/ .ant-table-small > .ant-table-content > .ant-table-body {
margin: 0;
}
/deep/ .light-row {
background-color: #fff;
}
/deep/ .dark-row {
background-color: #f9f9f9;
}
.metric-card {
margin-left: -24px;
margin-right: -24px;
margin-top: -16px;
margin-bottom: 12px;
overflow-y: auto;
margin-bottom: 100px;
}
</style>

View File

@ -20,26 +20,56 @@
package com.cloud.utils;
import java.io.File;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
public class LogUtils {
public static final Logger s_logger = Logger.getLogger(LogUtils.class);
public static final Logger LOGGER = Logger.getLogger(LogUtils.class);
private static String configFileLocation = null;
public static void initLog4j(String log4jConfigFileName) {
assert (log4jConfigFileName != null);
File file = PropertiesUtil.findConfigFile(log4jConfigFileName);
if (file != null) {
s_logger.info("log4j configuration found at " + file.getAbsolutePath());
DOMConfigurator.configureAndWatch(file.getAbsolutePath());
configFileLocation = file.getAbsolutePath();
DOMConfigurator.configureAndWatch(configFileLocation);
} else {
String nameWithoutExtension = log4jConfigFileName.substring(0, log4jConfigFileName.lastIndexOf('.'));
file = PropertiesUtil.findConfigFile(nameWithoutExtension + ".properties");
if (file != null) {
s_logger.info("log4j configuration found at " + file.getAbsolutePath());
DOMConfigurator.configureAndWatch(file.getAbsolutePath());
configFileLocation = file.getAbsolutePath();
DOMConfigurator.configureAndWatch(configFileLocation);
}
}
if (configFileLocation != null) {
LOGGER.info("log4j configuration found at " + configFileLocation);
}
}
public static Set<String> getLogFileNames() {
Set<String> fileNames = new HashSet<>();
Enumeration appenders = LOGGER.getRootLogger().getAllAppenders();
int appenderCount=0;
while (appenders.hasMoreElements()) {
++appenderCount;
Appender currAppender = (Appender) appenders.nextElement();
if (currAppender instanceof FileAppender) {
String fileName =((FileAppender) currAppender).getFile();
fileNames.add(fileName);
LOGGER.debug(String.format("file for %s : %s", currAppender.getName(), fileName));
} else if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("not counting %s as a file.", currAppender.getName()));
}
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(String.format("out of %d appenders, %d are log files", appenderCount, fileNames.size()));
}
return fileNames;
}
}