You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by nv...@apache.org on 2022/04/22 11:48:25 UTC
[cloudstack] branch main updated: Mshost stats (#5588)
This is an automated email from the ASF dual-hosted git repository.
nvazquez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 545e89c1cb Mshost stats (#5588)
545e89c1cb is described below
commit 545e89c1cb564dbec7ba8e122f6bab77cdcbdfd1
Author: dahn <da...@shapeblue.com>
AuthorDate: Fri Apr 22 13:48:19 2022 +0200
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 <12...@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 <12...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/response/DbMetricsResponse.java
Co-authored-by: sureshanaparti <12...@users.noreply.github.com>
* Update framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerHostDao.java
Co-authored-by: Rodrigo D. Lopez <19...@users.noreply.github.com>
* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java
Co-authored-by: Rodrigo D. Lopez <19...@users.noreply.github.com>
* Update api/src/main/java/org/apache/cloudstack/api/response/ManagementServerResponse.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update api/src/main/java/org/apache/cloudstack/api/response/ManagementServerResponse.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update server/src/main/java/com/cloud/server/StatsCollector.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerHostDao.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update server/src/main/java/com/cloud/server/StatsCollector.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update server/src/main/java/com/cloud/server/StatsCollector.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
* Update server/src/main/java/com/cloud/server/StatsCollector.java
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@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 <da...@onecht.net>
Co-authored-by: sureshanaparti <12...@users.noreply.github.com>
Co-authored-by: Rodrigo D. Lopez <19...@users.noreply.github.com>
Co-authored-by: Daniel Augusto Veronezi Salvador <38...@users.noreply.github.com>
Co-authored-by: Rohit Yadav <ro...@shapeblue.com>
---
.../cloud/server/ManagementServerHostStats.java | 113 +
.../org/apache/cloudstack/api/ApiConstants.java | 9 +-
.../api/response/ManagementServerResponse.java | 103 +-
.../management/ManagementServerStatus.java | 45 +
client/src/main/webapp/WEB-INF/web.xml | 3 +
.../cloud/agent/manager/ConnectedAgentAttache.java | 2 +-
.../src/main/java/com/cloud/host/dao/HostDao.java | 7 +
.../main/java/com/cloud/host/dao/HostDaoImpl.java | 12 +
.../spring-engine-schema-core-daos-context.xml | 2 +
.../resources/META-INF/db/schema-41610to41700.sql | 84 +-
.../java/com/cloud/cluster/ClusterManager.java | 52 +-
.../java/com/cloud/cluster/ClusterManagerImpl.java | 56 +-
.../java/com/cloud/cluster/ClusterServicePdu.java | 1 +
.../cloud/cluster/ManagementServerStatusVO.java | 184 +
.../cloud/cluster/dao/ManagementServerHostDao.java | 7 +-
.../cluster/dao/ManagementServerStatusDao.java | 24 +
.../cluster/dao/ManagementServerStatusDaoImpl.java | 48 +
.../src/main/java/com/cloud/utils/db/DbUtil.java | 42 +-
.../web/CloudStackContextLoaderListener.java | 3 +-
.../apache/cloudstack/api/ListDbMetricsCmd.java | 56 +
.../apache/cloudstack/api/ListMgmtsMetricsCmd.java | 56 +
.../cloudstack/api/ListUsageServerMetricsCmd.java | 57 +
.../org/apache/cloudstack/api/MetricConstants.java | 56 +
.../apache/cloudstack/metrics/MetricsService.java | 8 +
.../cloudstack/metrics/MetricsServiceImpl.java | 379 +-
.../response/ClusterMetricsResponse.java | 2 +-
.../cloudstack/response/DbMetricsResponse.java | 107 +
.../cloudstack/response/HostMetricsSummary.java | 51 +
.../response/ManagementServerMetricsResponse.java | 211 +
.../response/UsageServerMetricsResponse.java | 68 +
.../cloudstack/response/ZoneMetricsResponse.java | 2 +-
.../cloudstack/metrics/MetricsServiceImplTest.java | 2 +
server/pom.xml | 10 +
server/src/main/java/com/cloud/api/ApiDBUtils.java | 9 +
.../java/com/cloud/api/ApiSessionListener.java | 90 +
.../java/com/cloud/api/query/QueryManagerImpl.java | 42 +-
.../api/query/dao/ManagementServerJoinDao.java | 23 +
.../api/query/dao/ManagementServerJoinDaoImpl.java | 23 +
.../cloud/api/query/vo/ManagementServerJoinVO.java | 173 +
.../java/com/cloud/server/DbStatsCollection.java | 31 +
.../server/ManagementServerHostStatsEntry.java | 456 +
.../main/java/com/cloud/server/StatsCollector.java | 808 +-
server/src/test/async-job-component.xml | 1 +
.../java/com/cloud/server/StatsCollectorTest.java | 53 +-
test/integration/smoke/test_metrics_api.py | 229 +-
ui/package-lock.json | 32845 ++++++++++++++++++-
ui/public/locales/el_GR.json | 1 -
ui/public/locales/en.json | 36 +-
ui/src/components/view/DetailsTab.vue | 2 +-
ui/src/config/section/infra.js | 13 +-
ui/src/config/section/infra/managementServers.js | 41 +
ui/src/core/lazy_lib/icons_use.js | 6 +
ui/src/views/AutogenView.vue | 2 +-
ui/src/views/infra/InfraSummary.vue | 2 +-
ui/src/views/infra/Metrics.vue | 235 +
utils/src/main/java/com/cloud/utils/LogUtils.java | 40 +-
56 files changed, 36408 insertions(+), 615 deletions(-)
diff --git a/api/src/main/java/com/cloud/server/ManagementServerHostStats.java b/api/src/main/java/com/cloud/server/ManagementServerHostStats.java
new file mode 100644
index 0000000000..1f201d7689
--- /dev/null
+++ b/api/src/main/java/com/cloud/server/ManagementServerHostStats.java
@@ -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();
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 643060cee1..70ae181973 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -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";
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ManagementServerResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ManagementServerResponse.java
index efb7d878dd..0289e8f9e3 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/ManagementServerResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/ManagementServerResponse.java
@@ -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;
+ }
}
diff --git a/api/src/main/java/org/apache/cloudstack/management/ManagementServerStatus.java b/api/src/main/java/org/apache/cloudstack/management/ManagementServerStatus.java
new file mode 100644
index 0000000000..bae8e35734
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/management/ManagementServerStatus.java
@@ -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();
+}
diff --git a/client/src/main/webapp/WEB-INF/web.xml b/client/src/main/webapp/WEB-INF/web.xml
index 03f7d15db6..9a3d8bc5b2 100644
--- a/client/src/main/webapp/WEB-INF/web.xml
+++ b/client/src/main/webapp/WEB-INF/web.xml
@@ -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>
diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/ConnectedAgentAttache.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/ConnectedAgentAttache.java
index f11a105b2a..82423205a6 100644
--- a/engine/orchestration/src/main/java/com/cloud/agent/manager/ConnectedAgentAttache.java
+++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/ConnectedAgentAttache.java
@@ -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);
diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
index 1ea65e26e7..54d4a5e9ca 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
@@ -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);
}
diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
index 8b54c48bf5..8e1f8f470d 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
@@ -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();
diff --git a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
index 2b0b56b468..d7b7d129f2 100644
--- a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
+++ b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
@@ -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" />
diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql b/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql
index e6fd3708ca..7f82ecf475 100644
--- a/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql
+++ b/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql
@@ -698,4 +698,86 @@ CREATE VIEW `cloud`.`domain_router_view` AS
left join
`cloud`.`async_job` ON async_job.instance_id = vm_instance.id
and async_job.instance_type = 'DomainRouter'
- and async_job.job_status = 0;
\ No newline at end of file
+ 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`)));
diff --git a/framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java b/framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java
index c4a800c795..1b1406c1ce 100644
--- a/framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java
+++ b/framework/cluster/src/main/java/com/cloud/cluster/ClusterManager.java
@@ -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);
+ }
}
diff --git a/framework/cluster/src/main/java/com/cloud/cluster/ClusterManagerImpl.java b/framework/cluster/src/main/java/com/cloud/cluster/ClusterManagerImpl.java
index 600b25782f..289638fe22 100644
--- a/framework/cluster/src/main/java/com/cloud/cluster/ClusterManagerImpl.java
+++ b/framework/cluster/src/main/java/com/cloud/cluster/ClusterManagerImpl.java
@@ -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
}
}
}
-
}
diff --git a/framework/cluster/src/main/java/com/cloud/cluster/ClusterServicePdu.java b/framework/cluster/src/main/java/com/cloud/cluster/ClusterServicePdu.java
index 9f97469f78..ca5f1840ba 100644
--- a/framework/cluster/src/main/java/com/cloud/cluster/ClusterServicePdu.java
+++ b/framework/cluster/src/main/java/com/cloud/cluster/ClusterServicePdu.java
@@ -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;
diff --git a/framework/cluster/src/main/java/com/cloud/cluster/ManagementServerStatusVO.java b/framework/cluster/src/main/java/com/cloud/cluster/ManagementServerStatusVO.java
new file mode 100644
index 0000000000..6daeffe625
--- /dev/null
+++ b/framework/cluster/src/main/java/com/cloud/cluster/ManagementServerStatusVO.java
@@ -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();
+ }
+}
diff --git a/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerHostDao.java b/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerHostDao.java
index 610826932a..be81b5fe04 100644
--- a/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerHostDao.java
+++ b/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerHostDao.java
@@ -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);
}
diff --git a/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerStatusDao.java b/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerStatusDao.java
new file mode 100644
index 0000000000..62f284386f
--- /dev/null
+++ b/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerStatusDao.java
@@ -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);
+}
diff --git a/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerStatusDaoImpl.java b/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerStatusDaoImpl.java
new file mode 100644
index 0000000000..d40a104c2d
--- /dev/null
+++ b/framework/cluster/src/main/java/com/cloud/cluster/dao/ManagementServerStatusDaoImpl.java
@@ -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;
+ }
+}
diff --git a/framework/db/src/main/java/com/cloud/utils/db/DbUtil.java b/framework/db/src/main/java/com/cloud/utils/db/DbUtil.java
index f7f785062e..86a61bc69c 100644
--- a/framework/db/src/main/java/com/cloud/utils/db/DbUtil.java
+++ b/framework/db/src/main/java/com/cloud/utils/db/DbUtil.java
@@ -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;
+ }
+
}
diff --git a/framework/spring/module/src/main/java/org/apache/cloudstack/spring/module/web/CloudStackContextLoaderListener.java b/framework/spring/module/src/main/java/org/apache/cloudstack/spring/module/web/CloudStackContextLoaderListener.java
index a90d6a5534..549c69d5da 100644
--- a/framework/spring/module/src/main/java/org/apache/cloudstack/spring/module/web/CloudStackContextLoaderListener.java
+++ b/framework/spring/module/src/main/java/org/apache/cloudstack/spring/module/web/CloudStackContextLoaderListener.java
@@ -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);
}
-
}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListDbMetricsCmd.java b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListDbMetricsCmd.java
new file mode 100644
index 0000000000..1100164dc4
--- /dev/null
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListDbMetricsCmd.java
@@ -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();
+ }
+}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListMgmtsMetricsCmd.java b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListMgmtsMetricsCmd.java
new file mode 100644
index 0000000000..c3c9319bf9
--- /dev/null
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListMgmtsMetricsCmd.java
@@ -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);
+ }
+}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListUsageServerMetricsCmd.java b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListUsageServerMetricsCmd.java
new file mode 100644
index 0000000000..f39b8a4729
--- /dev/null
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListUsageServerMetricsCmd.java
@@ -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();
+ }
+}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/api/MetricConstants.java b/plugins/metrics/src/main/java/org/apache/cloudstack/api/MetricConstants.java
new file mode 100644
index 0000000000..19a1cd4056
--- /dev/null
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/api/MetricConstants.java
@@ -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";
+}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsService.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsService.java
index 26c52f74b1..ee67fe86ba 100644
--- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsService.java
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsService.java
@@ -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();
}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
index df6dc09cf3..2968314938 100644
--- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java
@@ -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,61 +551,152 @@ 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());
+ metricsResponse.setResources(hostMetrics.getUpResources(), hostMetrics.getTotalResources());
+ addHostCpuMetricsToResponse(metricsResponse, clusterId, hostMetrics);
+ addHostMemoryMetricsToResponse(metricsResponse, clusterId, hostMetrics);
+
+ metricsResponse.setHasAnnotation(clusterResponse.hasAnnotation());
+ metricsResponses.add(metricsResponse);
+ }
+ 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()));
}
- // 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());
+ 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.");
}
- // 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.setHasAnnotation(clusterResponse.hasAnnotation());
+ 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(ListClustersMetricsCmd.class);
+ cmdList.add(ListDbMetricsCmd.class);
+ cmdList.add(ListHostsMetricsCmd.class);
cmdList.add(ListInfrastructureCmd.class);
- cmdList.add(ListVolumesMetricsCmd.class);
- cmdList.add(ListVMsMetricsCmd.class);
+ cmdList.add(ListMgmtsMetricsCmd.class);
cmdList.add(ListStoragePoolsMetricsCmd.class);
- cmdList.add(ListHostsMetricsCmd.class);
- cmdList.add(ListClustersMetricsCmd.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();
}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/ClusterMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/ClusterMetricsResponse.java
index a12ecd3b4f..18ea57d711 100644
--- a/plugins/metrics/src/main/java/org/apache/cloudstack/response/ClusterMetricsResponse.java
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/ClusterMetricsResponse.java
@@ -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;
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/DbMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/DbMetricsResponse.java
new file mode 100644
index 0000000000..8abf5b585a
--- /dev/null
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/DbMetricsResponse.java
@@ -0,0 +1,107 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.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;
+ }
+}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsSummary.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsSummary.java
new file mode 100644
index 0000000000..e3610c8f1a
--- /dev/null
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsSummary.java
@@ -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);
+}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/ManagementServerMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/ManagementServerMetricsResponse.java
new file mode 100644
index 0000000000..ae0f57b967
--- /dev/null
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/ManagementServerMetricsResponse.java
@@ -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);
+ }
+}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/UsageServerMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/UsageServerMetricsResponse.java
new file mode 100644
index 0000000000..845d223ded
--- /dev/null
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/UsageServerMetricsResponse.java
@@ -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;
+ }
+}
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/ZoneMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/ZoneMetricsResponse.java
index b3c1f86a68..c6bdda3de3 100644
--- a/plugins/metrics/src/main/java/org/apache/cloudstack/response/ZoneMetricsResponse.java
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/ZoneMetricsResponse.java
@@ -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;
diff --git a/plugins/metrics/src/test/java/org/apache/cloudstack/metrics/MetricsServiceImplTest.java b/plugins/metrics/src/test/java/org/apache/cloudstack/metrics/MetricsServiceImplTest.java
index 59ebaf7525..ddc4d8b30b 100644
--- a/plugins/metrics/src/test/java/org/apache/cloudstack/metrics/MetricsServiceImplTest.java
+++ b/plugins/metrics/src/test/java/org/apache/cloudstack/metrics/MetricsServiceImplTest.java
@@ -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 {
diff --git a/server/pom.xml b/server/pom.xml
index 3f44277a71..ba2247713e 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -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>
diff --git a/server/src/main/java/com/cloud/api/ApiDBUtils.java b/server/src/main/java/com/cloud/api/ApiDBUtils.java
index 221202f7a9..bd11136b63 100644
--- a/server/src/main/java/com/cloud/api/ApiDBUtils.java
+++ b/server/src/main/java/com/cloud/api/ApiDBUtils.java
@@ -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);
}
diff --git a/server/src/main/java/com/cloud/api/ApiSessionListener.java b/server/src/main/java/com/cloud/api/ApiSessionListener.java
new file mode 100644
index 0000000000..6bb853d76c
--- /dev/null
+++ b/server/src/main/java/com/cloud/api/ApiSessionListener.java
@@ -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());
+ }
+ }
+ }
+}
diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
index 6a78b32dcb..4bc5ccd56d 100644
--- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java
@@ -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;
}
diff --git a/server/src/main/java/com/cloud/api/query/dao/ManagementServerJoinDao.java b/server/src/main/java/com/cloud/api/query/dao/ManagementServerJoinDao.java
new file mode 100644
index 0000000000..bf45f80151
--- /dev/null
+++ b/server/src/main/java/com/cloud/api/query/dao/ManagementServerJoinDao.java
@@ -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> {
+}
diff --git a/server/src/main/java/com/cloud/api/query/dao/ManagementServerJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/ManagementServerJoinDaoImpl.java
new file mode 100644
index 0000000000..cc5620144c
--- /dev/null
+++ b/server/src/main/java/com/cloud/api/query/dao/ManagementServerJoinDaoImpl.java
@@ -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 {
+}
diff --git a/server/src/main/java/com/cloud/api/query/vo/ManagementServerJoinVO.java b/server/src/main/java/com/cloud/api/query/vo/ManagementServerJoinVO.java
new file mode 100644
index 0000000000..be1a4c6f7f
--- /dev/null
+++ b/server/src/main/java/com/cloud/api/query/vo/ManagementServerJoinVO.java
@@ -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;
+ }
+}
diff --git a/server/src/main/java/com/cloud/server/DbStatsCollection.java b/server/src/main/java/com/cloud/server/DbStatsCollection.java
new file mode 100644
index 0000000000..cb07582705
--- /dev/null
+++ b/server/src/main/java/com/cloud/server/DbStatsCollection.java
@@ -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";
+
+}
diff --git a/server/src/main/java/com/cloud/server/ManagementServerHostStatsEntry.java b/server/src/main/java/com/cloud/server/ManagementServerHostStatsEntry.java
new file mode 100644
index 0000000000..fb0084f3d7
--- /dev/null
+++ b/server/src/main/java/com/cloud/server/ManagementServerHostStatsEntry.java
@@ -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;
+ }
+}
diff --git a/server/src/main/java/com/cloud/server/StatsCollector.java b/server/src/main/java/com/cloud/server/StatsCollector.java
index ecea1318f1..252894c3cc 100644
--- a/server/src/main/java/com/cloud/server/StatsCollector.java
+++ b/server/src/main/java/com/cloud/server/StatsCollector.java
@@ -16,15 +16,24 @@
// under the License.
package com.cloud.server;
+import javax.inject.Inject;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+
+import java.lang.management.RuntimeMXBean;
import java.net.URI;
import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
@@ -32,8 +41,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import javax.inject.Inject;
-
+import com.cloud.utils.db.DbUtil;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
@@ -43,14 +51,17 @@ 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.managed.context.ManagedContextRunnable;
+import org.apache.cloudstack.management.ManagementServerHost;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
import org.apache.cloudstack.utils.graphite.GraphiteClient;
import org.apache.cloudstack.utils.graphite.GraphiteException;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.cloudstack.utils.usage.UsageUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.BooleanUtils;
@@ -61,6 +72,7 @@ import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.Pong;
+import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
@@ -74,9 +86,15 @@ import com.cloud.agent.api.VmNetworkStatsEntry;
import com.cloud.agent.api.VmStatsEntry;
import com.cloud.agent.api.VmStatsEntryBase;
import com.cloud.agent.api.VolumeStatsEntry;
+import com.cloud.api.ApiSessionListener;
import com.cloud.capacity.CapacityManager;
+import com.cloud.cluster.ClusterManager;
+import com.cloud.cluster.ClusterManagerListener;
+import com.cloud.cluster.ClusterServicePdu;
import com.cloud.cluster.ManagementServerHostVO;
+import com.cloud.cluster.ManagementServerStatusVO;
import com.cloud.cluster.dao.ManagementServerHostDao;
+import com.cloud.cluster.dao.ManagementServerStatusDao;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.ClusterDao;
@@ -111,6 +129,7 @@ import com.cloud.network.as.dao.CounterDao;
import com.cloud.org.Cluster;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceState;
+import com.cloud.serializer.GsonHelper;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.ImageStoreDetailsUtil;
@@ -126,11 +145,13 @@ import com.cloud.user.UserStatisticsVO;
import com.cloud.user.VmDiskStatisticsVO;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.user.dao.VmDiskStatisticsDao;
+import com.cloud.utils.LogUtils;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentMethodInterceptable;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory;
+import com.cloud.utils.db.DbProperties;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.SearchCriteria;
@@ -139,6 +160,7 @@ import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.MacAddress;
+import com.cloud.utils.script.Script;
import com.cloud.vm.NicVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
@@ -150,17 +172,46 @@ import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.dao.VmStatsDao;
+
+import com.codahale.metrics.JvmAttributeGaugeSet;
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.MetricSet;
+import com.codahale.metrics.jvm.BufferPoolMetricSet;
+import com.codahale.metrics.jvm.GarbageCollectorMetricSet;
+import com.codahale.metrics.jvm.MemoryUsageGaugeSet;
+import com.codahale.metrics.jvm.ThreadStatesGaugeSet;
import com.google.gson.Gson;
+import com.google.gson.JsonParseException;
+import com.google.gson.reflect.TypeToken;
+import com.sun.management.OperatingSystemMXBean;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
-import org.apache.commons.io.FileUtils;
/**
* Provides real time stats for various agent resources up to x seconds
*
+ * @startuml
+ *
+ * StatsCollector -> ClusterManager : register
+ * ClusterManager -> StatsCollector : onManagementNodeJoined
+ * StatsCollector -> list : add MS
+ * ClusterManager -> StatsCollector : onManagementNodeJoined
+ * StatsCollector -> list : add MS to send list
+ * StatsCollector -> collector : update own status
+ * StatsCollector -> list : get all ms ids
+ * StatsCollector -> ClusterManager : update status for my (ms id) to all ms_ids
+ * ClusterManager -> ClusterManager : update ms_ids on status on (ms id)
+ * ClusterManager -> StatsCollector : onManagementNodeLeft
+ * StatsCollector -> list : add MS
+ * ClusterManager -> StatsCollector : status data updated for (ms id)
+ * StatsCollector -> StatsCollector : update entry for (ms id)
+ * ClusterManager -> StatsCollector : onManagementNodeLeft
+ * StatsCollector -> list : add MS
+ * @enduml
*/
@Component
-public class StatsCollector extends ManagerBase implements ComponentMethodInterceptable, Configurable {
+public class StatsCollector extends ManagerBase implements ComponentMethodInterceptable, Configurable, DbStatsCollection {
public static enum ExternalStatsProtocol {
NONE("none"), GRAPHITE("graphite"), INFLUXDB("influxdb");
@@ -176,7 +227,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
}
- public static final Logger s_logger = Logger.getLogger(StatsCollector.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(StatsCollector.class);
private static final int UNDEFINED_PORT_VALUE = -1;
@@ -213,24 +264,37 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
private static final String INFLUXDB_HOST_MEASUREMENT = "host_stats";
private static final String INFLUXDB_VM_MEASUREMENT = "vm_stats";
- private static final ConfigKey<Integer> vmDiskStatsInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vm.disk.stats.interval", "0",
+ public static final ConfigKey<Integer> MANAGEMENT_SERVER_STATUS_COLLECTION_INTERVAL = new ConfigKey<>("Advanced",
+ Integer.class, "management.server.stats.interval", "60",
+ "Time interval in seconds, for management servers stats collection. Set to <= 0 to disable management servers stats.", false);
+ private static final ConfigKey<Integer> DATABASE_SERVER_STATUS_COLLECTION_INTERVAL = new ConfigKey<>("Advanced",
+ Integer.class, "database.server.stats.interval", "60",
+ "Time interval in seconds, for database servers stats collection. Set to <= 0 to disable database servers stats.", false);
+ private static final ConfigKey<Integer> DATABASE_SERVER_LOAD_HISTORY_RETENTION_NUMBER = new ConfigKey<>("Advanced",
+ Integer.class, "database.server.stats.retention", "3",
+ "The number of queries/seconds values to retain in history. This will define for how many periods of 'database.server.stats.interval' seconds, the queries/seconds values will be kept in memory",
+ true);
+ private static final ConfigKey<Integer> vmDiskStatsInterval = new ConfigKey<>("Advanced", Integer.class, "vm.disk.stats.interval", "0",
"Interval (in seconds) to report vm disk statistics. Vm disk statistics will be disabled if this is set to 0 or less than 0.", false);
- private static final ConfigKey<Integer> vmDiskStatsIntervalMin = new ConfigKey<Integer>("Advanced", Integer.class, "vm.disk.stats.interval.min", "300",
+ private static final ConfigKey<Integer> vmDiskStatsIntervalMin = new ConfigKey<>("Advanced", Integer.class, "vm.disk.stats.interval.min", "300",
"Minimal interval (in seconds) to report vm disk statistics. If vm.disk.stats.interval is smaller than this, use this to report vm disk statistics.", false);
- private static final ConfigKey<Integer> vmNetworkStatsInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vm.network.stats.interval", "0",
+ private static final ConfigKey<Integer> vmNetworkStatsInterval = new ConfigKey<>("Advanced", Integer.class, "vm.network.stats.interval", "0",
"Interval (in seconds) to report vm network statistics (for Shared networks). Vm network statistics will be disabled if this is set to 0 or less than 0.", false);
- private static final ConfigKey<Integer> vmNetworkStatsIntervalMin = new ConfigKey<Integer>("Advanced", Integer.class, "vm.network.stats.interval.min", "300",
+ private static final ConfigKey<Integer> vmNetworkStatsIntervalMin = new ConfigKey<>("Advanced", Integer.class, "vm.network.stats.interval.min", "300",
"Minimal Interval (in seconds) to report vm network statistics (for Shared networks). If vm.network.stats.interval is smaller than this, use this to report vm network statistics.",
false);
- private static final ConfigKey<Integer> StatsTimeout = new ConfigKey<Integer>("Advanced", Integer.class, "stats.timeout", "60000",
+ private static final ConfigKey<Integer> StatsTimeout = new ConfigKey<>("Advanced", Integer.class, "stats.timeout", "60000",
"The timeout for stats call in milli seconds.", true,
ConfigKey.Scope.Cluster);
- private static final ConfigKey<String> statsOutputUri = new ConfigKey<String>("Advanced", String.class, "stats.output.uri", "",
+ private static final ConfigKey<String> statsOutputUri = new ConfigKey<>("Advanced", String.class, "stats.output.uri", "",
"URI to send StatsCollector statistics to. The collector is defined on the URI scheme. Example: graphite://graphite-hostaddress:port or influxdb://influxdb-hostaddress/dbname. Note that the port is optional, if not added the default port for the respective collector (graphite or influxdb) will be used. Additionally, the database name '/dbname' is also optional; default db name is 'cloudstack'. You must create and configure the database if using influxdb.",
true);
protected static ConfigKey<Boolean> vmStatsIncrementMetrics = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.stats.increment.metrics", "true",
"When set to 'true', VM metrics(NetworkReadKBs, NetworkWriteKBs, DiskWriteKBs, DiskReadKBs, DiskReadIOs and DiskWriteIOs) that are collected from the hypervisor are summed before being returned."
+ "On the other hand, when set to 'false', the VM metrics API will just display the latest metrics collected.", true);
+ private static final ConfigKey<Boolean> VM_STATS_INCREMENT_METRICS_IN_MEMORY = new ConfigKey<>("Advanced", Boolean.class, "vm.stats.increment.metrics.in.memory", "true",
+ "When set to 'true', VM metrics(NetworkReadKBs, NetworkWriteKBs, DiskWriteKBs, DiskReadKBs, DiskReadIOs and DiskWriteIOs) that are collected from the hypervisor are summed and stored in memory. "
+ + "On the other hand, when set to 'false', the VM metrics API will just display the latest metrics collected.", true);
protected static ConfigKey<Integer> vmStatsMaxRetentionTime = new ConfigKey<Integer>("Advanced", Integer.class, "vm.stats.max.retention.time", "1",
"The maximum time (in minutes) for keeping VM stats records in the database. The VM stats cleanup process will be disabled if this is set to 0 or less than 0.", true);
@@ -268,8 +332,6 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
@Inject
private VmDiskStatisticsDao _vmDiskStatsDao;
@Inject
- private ManagementServerHostDao _msHostDao;
- @Inject
private UserStatisticsDao _userStatsDao;
@Inject
private NicDao _nicDao;
@@ -303,12 +365,19 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
private ImageStoreDetailsUtil imageStoreDetailsUtil;
@Inject
private ManagementServerHostDao managementServerHostDao;
+ // stats collector is now a clustered agent
+ @Inject
+ private ClusterManager clusterManager;
+ @Inject
+ private ManagementServerStatusDao managementServerStatusDao;
- private ConcurrentHashMap<Long, HostStats> _hostStats = new ConcurrentHashMap<Long, HostStats>();
- protected ConcurrentHashMap<Long, VmStats> _VmStats = new ConcurrentHashMap<Long, VmStats>();
- private final Map<String, VolumeStats> _volumeStats = new ConcurrentHashMap<String, VolumeStats>();
- private ConcurrentHashMap<Long, StorageStats> _storageStats = new ConcurrentHashMap<Long, StorageStats>();
- private ConcurrentHashMap<Long, StorageStats> _storagePoolStats = new ConcurrentHashMap<Long, StorageStats>();
+ private final ConcurrentHashMap<String, ManagementServerHostStats> managementServerHostStats = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<String, Object> dbStats = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<Long, HostStats> _hostStats = new ConcurrentHashMap<>();
+ protected ConcurrentHashMap<Long, VmStats> _VmStats = new ConcurrentHashMap<>();
+ private final Map<String, VolumeStats> _volumeStats = new ConcurrentHashMap<>();
+ private ConcurrentHashMap<Long, StorageStats> _storageStats = new ConcurrentHashMap<>();
+ private ConcurrentHashMap<Long, StorageStats> _storagePoolStats = new ConcurrentHashMap<>();
private static final long DEFAULT_INITIAL_DELAY = 15000L;
@@ -333,6 +402,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
private boolean _dailyOrHourly = false;
protected long managementServerNodeId = ManagementServerNode.getManagementServerId();
protected long msId = managementServerNodeId;
+ final static MetricRegistry METRIC_REGISTRY = new MetricRegistry();
public static StatsCollector getInstance() {
return s_instance;
@@ -350,8 +420,30 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
@Override
public boolean start() {
init(_configDao.getConfiguration());
+ registerAll("gc", new GarbageCollectorMetricSet(), METRIC_REGISTRY);
+ registerAll("buffers", new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()), METRIC_REGISTRY);
+ registerAll("memory", new MemoryUsageGaugeSet(), METRIC_REGISTRY);
+ registerAll("threads", new ThreadStatesGaugeSet(), METRIC_REGISTRY);
+ registerAll("jvm", new JvmAttributeGaugeSet(), METRIC_REGISTRY);
return true;
}
+ @Override
+ public boolean stop() {
+ _executor.shutdown();
+ return true;
+ }
+
+ private void registerAll(String prefix, MetricSet metricSet, MetricRegistry registry) {
+ String registryTemplate = new String(prefix + "%s");
+ for (Map.Entry<String, Metric> entry : metricSet.getMetrics().entrySet()) {
+ String registryName = String.format(registryTemplate, entry.getKey());
+ if (entry.getValue() instanceof MetricSet) {
+ registerAll(registryName, (MetricSet) entry.getValue(), registry);
+ } else {
+ registry.register(registryName, entry.getValue());
+ }
+ }
+ }
protected void init(Map<String, String> configs) {
_executor = Executors.newScheduledThreadPool(6, new NamedThreadFactory("StatsCollector"));
@@ -361,6 +453,11 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
storageStatsInterval = NumbersUtil.parseLong(configs.get("storage.stats.interval"), ONE_MINUTE_IN_MILLISCONDS);
volumeStatsInterval = NumbersUtil.parseLong(configs.get("volume.stats.interval"), ONE_MINUTE_IN_MILLISCONDS);
autoScaleStatsInterval = NumbersUtil.parseLong(configs.get("autoscale.stats.interval"), ONE_MINUTE_IN_MILLISCONDS);
+ ManagementServerStatusAdministrator managementServerStatusAdministrator = new ManagementServerStatusAdministrator();
+ clusterManager.registerStatusAdministrator(managementServerStatusAdministrator);
+ clusterManager.registerListener(managementServerStatusAdministrator);
+
+ gson = GsonHelper.getGson();
String statsUri = statsOutputUri.value();
if (StringUtils.isNotBlank(statsUri)) {
@@ -371,7 +468,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
try {
externalStatsType = ExternalStatsProtocol.valueOf(externalStatsScheme.toUpperCase());
} catch (IllegalArgumentException e) {
- s_logger.error(externalStatsScheme + " is not a valid protocol for external statistics. No statistics will be send.");
+ LOGGER.error(externalStatsScheme + " is not a valid protocol for external statistics. No statistics will be send.");
}
if (StringUtils.isNotEmpty(uri.getHost())) {
@@ -394,7 +491,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
} catch (URISyntaxException e) {
- s_logger.error("Failed to parse external statistics URI: ", e);
+ LOGGER.error("Failed to parse external statistics URI: ", e);
}
}
@@ -405,11 +502,14 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
if (vmStatsInterval > 0) {
_executor.scheduleWithFixedDelay(new VmStatsCollector(), DEFAULT_INITIAL_DELAY, vmStatsInterval, TimeUnit.MILLISECONDS);
} else {
- s_logger.info("Skipping collect VM stats. The global parameter vm.stats.interval is set to 0 or less than 0.");
+ LOGGER.info("Skipping collect VM stats. The global parameter vm.stats.interval is set to 0 or less than 0.");
}
_executor.scheduleWithFixedDelay(new VmStatsCleaner(), DEFAULT_INITIAL_DELAY, 60000L, TimeUnit.MILLISECONDS);
+ scheduleCollection(MANAGEMENT_SERVER_STATUS_COLLECTION_INTERVAL, new ManagementServerCollector(), 1L);
+ scheduleCollection(DATABASE_SERVER_STATUS_COLLECTION_INTERVAL, new DbCollector(), 0L);
+
if (storageStatsInterval > 0) {
_executor.scheduleWithFixedDelay(new StorageCollector(), DEFAULT_INITIAL_DELAY, storageStatsInterval, TimeUnit.MILLISECONDS);
}
@@ -420,26 +520,26 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
if (vmDiskStatsInterval.value() > 0) {
if (vmDiskStatsInterval.value() < vmDiskStatsIntervalMin.value()) {
- s_logger.debug("vm.disk.stats.interval - " + vmDiskStatsInterval.value() + " is smaller than vm.disk.stats.interval.min - " + vmDiskStatsIntervalMin.value()
+ LOGGER.debug("vm.disk.stats.interval - " + vmDiskStatsInterval.value() + " is smaller than vm.disk.stats.interval.min - " + vmDiskStatsIntervalMin.value()
+ ", so use vm.disk.stats.interval.min");
_executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsIntervalMin.value(), vmDiskStatsIntervalMin.value(), TimeUnit.SECONDS);
} else {
_executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval.value(), vmDiskStatsInterval.value(), TimeUnit.SECONDS);
}
} else {
- s_logger.debug("vm.disk.stats.interval - " + vmDiskStatsInterval.value() + " is 0 or less than 0, so not scheduling the vm disk stats thread");
+ LOGGER.debug("vm.disk.stats.interval - " + vmDiskStatsInterval.value() + " is 0 or less than 0, so not scheduling the vm disk stats thread");
}
if (vmNetworkStatsInterval.value() > 0) {
if (vmNetworkStatsInterval.value() < vmNetworkStatsIntervalMin.value()) {
- s_logger.debug("vm.network.stats.interval - " + vmNetworkStatsInterval.value() + " is smaller than vm.network.stats.interval.min - "
+ LOGGER.debug("vm.network.stats.interval - " + vmNetworkStatsInterval.value() + " is smaller than vm.network.stats.interval.min - "
+ vmNetworkStatsIntervalMin.value() + ", so use vm.network.stats.interval.min");
_executor.scheduleAtFixedRate(new VmNetworkStatsTask(), vmNetworkStatsIntervalMin.value(), vmNetworkStatsIntervalMin.value(), TimeUnit.SECONDS);
} else {
_executor.scheduleAtFixedRate(new VmNetworkStatsTask(), vmNetworkStatsInterval.value(), vmNetworkStatsInterval.value(), TimeUnit.SECONDS);
}
} else {
- s_logger.debug("vm.network.stats.interval - " + vmNetworkStatsInterval.value() + " is 0 or less than 0, so not scheduling the vm network stats thread");
+ LOGGER.debug("vm.network.stats.interval - " + vmNetworkStatsInterval.value() + " is 0 or less than 0, so not scheduling the vm network stats thread");
}
if (volumeStatsInterval > 0) {
@@ -481,7 +581,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
_dailyOrHourly = false;
}
if (_usageAggregationRange < UsageUtils.USAGE_AGGREGATION_RANGE_MIN) {
- s_logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + UsageUtils.USAGE_AGGREGATION_RANGE_MIN);
+ LOGGER.warn("Usage stats job aggregation range is to small, using the minimum value of " + UsageUtils.USAGE_AGGREGATION_RANGE_MIN);
_usageAggregationRange = UsageUtils.USAGE_AGGREGATION_RANGE_MIN;
}
@@ -492,11 +592,23 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
if (mgmtServerVo != null) {
msId = mgmtServerVo.getId();
} else {
- s_logger.warn(String.format("Cannot find management server with msid [%s]. "
+ LOGGER.warn(String.format("Cannot find management server with msid [%s]. "
+ "Therefore, VM stats will be recorded with the management server MAC address converted as a long in the mgmt_server_id column.", managementServerNodeId));
}
}
+ private void scheduleCollection(ConfigKey<Integer> statusCollectionInterval, AbstractStatsCollector collector, long delay) {
+ if (statusCollectionInterval.value() > 0) {
+ _executor.scheduleAtFixedRate(collector,
+ delay,
+ statusCollectionInterval.value(),
+ TimeUnit.SECONDS);
+ } else {
+ LOGGER.debug(String.format("%s - %d is 0 or less, so not scheduling the status collector thread",
+ statusCollectionInterval.key(), statusCollectionInterval.value()));
+ }
+ }
+
/**
* Configures the database name according to the URI path. For instance, if the URI is as influxdb://address:port/dbname, the database name will be 'dbname'.
*/
@@ -536,7 +648,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
@Override
protected void runInContext() {
try {
- s_logger.debug("HostStatsCollector is running...");
+ LOGGER.debug("HostStatsCollector is running...");
SearchCriteria<HostVO> sc = createSearchCriteriaForHostTypeRoutingStateUpAndNotInMaintenance();
@@ -544,13 +656,13 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
List<HostVO> hosts = _hostDao.search(sc, null);
for (HostVO host : hosts) {
- HostStatsEntry hostStatsEntry = (HostStatsEntry)_resourceMgr.getHostStatistics(host.getId());
+ HostStatsEntry hostStatsEntry = (HostStatsEntry) _resourceMgr.getHostStatistics(host.getId());
if (hostStatsEntry != null) {
hostStatsEntry.setHostVo(host);
metrics.put(hostStatsEntry.getHostId(), hostStatsEntry);
_hostStats.put(host.getId(), hostStatsEntry);
} else {
- s_logger.warn("The Host stats is null for host: " + host.getId());
+ LOGGER.warn("The Host stats is null for host: " + host.getId());
}
}
@@ -560,7 +672,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
updateGpuEnabledHostsDetails(hosts);
} catch (Throwable t) {
- s_logger.error("Error trying to retrieve host stats", t);
+ LOGGER.error("Error trying to retrieve host stats", t);
}
}
@@ -587,16 +699,496 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
@Override
- protected Point creteInfluxDbPoint(Object metricsObject) {
+ protected Point createInfluxDbPoint(Object metricsObject) {
return createInfluxDbPointForHostMetrics(metricsObject);
}
}
+ class DbCollector extends AbstractStatsCollector {
+ List<Double> loadHistory = new ArrayList<>();
+ DbCollector() {
+ dbStats.put(loadAvarages, loadHistory);
+ }
+ @Override
+ protected void runInContext() {
+ LOGGER.debug(String.format("%s is running...", this.getClass().getSimpleName()));
+
+ try {
+ int lastUptime = (dbStats.containsKey(uptime) ? (Integer) dbStats.get(uptime) : 0);
+ int lastQueries = (dbStats.containsKey(queries) ? (Integer) dbStats.get(queries) : 0);
+ getDynamicDataFromDB();
+ int interval = (Integer) dbStats.get(uptime) - lastUptime;
+ int activity = (Integer) dbStats.get(queries) - lastQueries;
+ loadHistory.add(0, Double.valueOf(activity / interval));
+ int maxsize = DATABASE_SERVER_LOAD_HISTORY_RETENTION_NUMBER.value();
+ while (loadHistory.size() > maxsize) {
+ loadHistory.remove(maxsize - 1);
+ }
+ } catch (Throwable e) {
+ // pokemon catch to make sure the thread stays running
+ LOGGER.error("db statistics collection failed due to " + e.getLocalizedMessage());
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("db statistics collection failed.", e);
+ }
+ }
+ }
+
+ private void getDynamicDataFromDB() {
+ Map<String, String> stats = DbUtil.getDbInfo("STATUS", queries, uptime);
+ dbStats.put(collectionTime, new Date());
+ dbStats.put(queries, (Integer.valueOf(stats.get(queries))));
+ dbStats.put(uptime, (Integer.valueOf(stats.get(uptime))));
+ }
+
+
+ @Override
+ protected Point createInfluxDbPoint(Object metricsObject) {
+ return null;
+ }
+ }
+
+ class ManagementServerCollector extends AbstractStatsCollector {
+ @Override
+ protected void runInContext() {
+ LOGGER.debug(String.format("%s is running...", this.getClass().getSimpleName()));
+ long msid = ManagementServerNode.getManagementServerId();
+ ManagementServerHostVO mshost = null;
+ ManagementServerHostStatsEntry hostStatsEntry = null;
+ try {
+ mshost = managementServerHostDao.findByMsid(msid);
+ // get local data
+ hostStatsEntry = getDataFrom(mshost);
+ managementServerHostStats.put(mshost.getUuid(), hostStatsEntry);
+ // send to other hosts
+ clusterManager.publishStatus(gson.toJson(hostStatsEntry));
+ } catch (Throwable t) {
+ // pokemon catch to make sure the thread stays running
+ LOGGER.error("Error trying to retrieve management server host statistics", t);
+ }
+ try {
+ // send to DB
+ storeStatus(hostStatsEntry, mshost);
+ } catch (Throwable t) {
+ // pokemon catch to make sure the thread stays running
+ LOGGER.error("Error trying to store management server host statistics", t);
+ }
+ }
+
+ private void storeStatus(ManagementServerHostStatsEntry hostStatsEntry, ManagementServerHostVO mshost) {
+ if (hostStatsEntry == null || mshost == null) {
+ return;
+ }
+ ManagementServerStatusVO msStats = managementServerStatusDao.findByMsId(hostStatsEntry.getManagementServerHostUuid());
+ if (msStats == null) {
+ LOGGER.info(String.format("creating new status info record for host %s - %s",
+ mshost.getName(),
+ hostStatsEntry.getManagementServerHostUuid()));
+ msStats = new ManagementServerStatusVO();
+ msStats.setMsId(hostStatsEntry.getManagementServerHostUuid());
+ }
+ msStats.setOsDistribution(hostStatsEntry.getOsDistribution()); // for now just the bunch details come later
+ msStats.setJavaName(hostStatsEntry.getJvmVendor());
+ msStats.setJavaVersion(hostStatsEntry.getJvmVersion());
+ Date startTime = new Date(hostStatsEntry.getJvmStartTime());
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(String.format("reporting starttime %s", startTime));
+ }
+ msStats.setLastJvmStart(startTime);
+ msStats.setLastSystemBoot(hostStatsEntry.getSystemBootTime());
+ msStats.setUpdated(new Date());
+ managementServerStatusDao.persist(msStats);
+ }
+
+ @NotNull
+ private ManagementServerHostStatsEntry getDataFrom(ManagementServerHostVO mshost) {
+ ManagementServerHostStatsEntry newEntry = new ManagementServerHostStatsEntry();
+ LOGGER.trace("Metrics collection start...");
+ newEntry.setManagementServerHostId(mshost.getId());
+ newEntry.setManagementServerHostUuid(mshost.getUuid());
+ newEntry.setDbLocal(isDbLocal());
+ newEntry.setUsageLocal(isUsageLocal());
+ retrieveSession(newEntry);
+ getJvmDimensions(newEntry);
+ LOGGER.trace("Metrics collection extra...");
+ getRuntimeData(newEntry);
+ getMemoryData(newEntry);
+ // newEntry must now include a pid!
+ getProcFileSystemData(newEntry);
+ // proc memory data has precedence over mbean memory data
+ getCpuData(newEntry);
+ getFileSystemData(newEntry);
+ getDataBaseStatistics(newEntry, mshost.getMsid());
+ gatherAllMetrics(newEntry);
+ LOGGER.trace("Metrics collection end!");
+ return newEntry;
+ }
+
+ private void retrieveSession(ManagementServerHostStatsEntry newEntry) {
+ long sessions = ApiSessionListener.getSessionCount();
+ newEntry.setSessions(sessions);
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(String.format("Sessions found in Api %d vs context %d", sessions,ApiSessionListener.getNumberOfSessions()));
+ } else {
+ LOGGER.debug("Sessions active: " + sessions);
+ }
+ }
+
+ private void getDataBaseStatistics(ManagementServerHostStatsEntry newEntry, long msid) {
+ int count = _hostDao.countByMs(msid);
+ newEntry.setAgentCount(count);
+ }
+
+ private void getMemoryData(@NotNull ManagementServerHostStatsEntry newEntry) {
+ MemoryMXBean mxBean = ManagementFactory.getMemoryMXBean();
+ newEntry.setTotalInit(mxBean.getHeapMemoryUsage().getInit() + mxBean.getNonHeapMemoryUsage().getInit());
+ newEntry.setTotalUsed(mxBean.getHeapMemoryUsage().getUsed() + mxBean.getNonHeapMemoryUsage().getUsed());
+ newEntry.setMaxJvmMemoryBytes(mxBean.getHeapMemoryUsage().getMax() + mxBean.getNonHeapMemoryUsage().getMax());
+ newEntry.setTotalCommitted(mxBean.getHeapMemoryUsage().getCommitted() + mxBean.getNonHeapMemoryUsage().getCommitted());
+ }
+
+ private void getCpuData(@NotNull ManagementServerHostStatsEntry newEntry) {
+ java.lang.management.OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean();
+ newEntry.setAvailableProcessors(bean.getAvailableProcessors());
+ newEntry.setLoadAverage(bean.getSystemLoadAverage());
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(String.format(
+ "Metrics processors - %d , loadavg - %f ",
+ newEntry.getAvailableProcessors(),
+ newEntry.getLoadAverage()));
+ }
+ if (bean instanceof OperatingSystemMXBean) {
+ OperatingSystemMXBean mxBean = (OperatingSystemMXBean) bean;
+ // if we got these from /proc, skip the bean
+ if (newEntry.getSystemMemoryTotal() == 0) {
+ newEntry.setSystemMemoryTotal(mxBean.getTotalPhysicalMemorySize());
+ }
+ if (newEntry.getSystemMemoryFree() == 0) {
+ newEntry.setSystemMemoryFree(mxBean.getFreePhysicalMemorySize());
+ }
+ if (newEntry.getSystemMemoryUsed() <= 0) {
+ newEntry.setSystemMemoryUsed(mxBean.getCommittedVirtualMemorySize());
+ }
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(String.format("data from 'OperatingSystemMXBean': total mem: %d, free mem: %d, used mem: %d",
+ newEntry.getSystemMemoryTotal(),
+ newEntry.getSystemMemoryFree(),
+ newEntry.getSystemMemoryUsed()));
+ }
+ }
+ }
+
+ private void getRuntimeData(@NotNull ManagementServerHostStatsEntry newEntry) {
+ final RuntimeMXBean mxBean = ManagementFactory.getRuntimeMXBean();
+ newEntry.setJvmUptime(mxBean.getUptime());
+ newEntry.setJvmStartTime(mxBean.getStartTime());
+ newEntry.setProcessId(mxBean.getPid());
+ newEntry.setJvmName(mxBean.getName());
+ newEntry.setJvmVendor(mxBean.getVmVendor());
+ newEntry.setJvmVersion(mxBean.getVmVersion());
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(String.format(
+ "Metrics uptime - %d , starttime - %d",
+ newEntry.getJvmUptime(),
+ newEntry.getJvmStartTime()));
+ }
+ }
+
+ private void getJvmDimensions(@NotNull ManagementServerHostStatsEntry newEntry) {
+ Runtime runtime = Runtime.getRuntime();
+ newEntry.setTotalJvmMemoryBytes(runtime.totalMemory());
+ newEntry.setFreeJvmMemoryBytes(runtime.freeMemory());
+ newEntry.setMaxJvmMemoryBytes(runtime.maxMemory());
+ //long maxMem = runtime.maxMemory();
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(String.format(
+ "Metrics proc - %d , maxMem - %d , totalMemory - %d , freeMemory - %f ",
+ newEntry.getAvailableProcessors(),
+ newEntry.getMaxJvmMemoryBytes(),
+ newEntry.getTotalJvmMemoryBytes(),
+ newEntry.getFreeJvmMemoryBytes()));
+ }
+ }
+
+ /**
+ * As for data from outside the JVM, we only rely on /proc/ contained data.
+ *
+ * @param newEntry item to add the information to
+ */
+ private void getProcFileSystemData(@NotNull ManagementServerHostStatsEntry newEntry) {
+ // this should be taken from ("cat /proc/version"), not sure how standard this /etc entry is
+ String OS = Script.runSimpleBashScript("cat /etc/os-release | grep PRETTY_NAME | cut -f2 -d '=' | tr -d '\"'");
+ newEntry.setOsDistribution(OS);
+ String kernel = Script.runSimpleBashScript("uname -r");
+ newEntry.setKernelVersion(kernel);
+ // if we got these from the bean, skip
+ if (newEntry.getSystemMemoryTotal() == 0) {
+ String mem = Script.runSimpleBashScript("cat /proc/meminfo | grep MemTotal | cut -f 2 -d ':' | tr -d 'a-zA-z '").trim();
+ newEntry.setSystemMemoryTotal(Long.parseLong(mem) * ByteScaleUtils.KiB);
+ LOGGER.info(String.format("system memory from /proc: %d", newEntry.getSystemMemoryTotal()));
+ }
+ if (newEntry.getSystemMemoryFree() == 0) {
+ String free = Script.runSimpleBashScript("cat /proc/meminfo | grep MemFree | cut -f 2 -d ':' | tr -d 'a-zA-z '").trim();
+ newEntry.setSystemMemoryFree(Long.parseLong(free) * ByteScaleUtils.KiB);
+ LOGGER.info(String.format("free memory from /proc: %d", newEntry.getSystemMemoryFree()));
+ }
+ if (newEntry.getSystemMemoryUsed() <= 0) {
+ String used = Script.runSimpleBashScript(String.format("ps -o rss= %d", newEntry.getPid()));
+ newEntry.setSystemMemoryUsed(Long.parseLong(used));
+ LOGGER.info(String.format("used memory from /proc: %d", newEntry.getSystemMemoryUsed()));
+ }
+ try {
+ String bootTime = Script.runSimpleBashScript("uptime -s");
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.ENGLISH);
+ Date date = formatter.parse(bootTime);
+ newEntry.setSystemBootTime(date);
+ } catch (ParseException e) {
+ LOGGER.error("can not retrieve system uptime");
+ }
+ String maxuse = Script.runSimpleBashScript(String.format("ps -o vsz= %d", newEntry.getPid()));
+ newEntry.setSystemMemoryVirtualSize(Long.parseLong(maxuse) * 1024);
+
+ newEntry.setSystemTotalCpuCycles(getSystemCpuCyclesTotal());
+ newEntry.setSystemLoadAverages(getCpuLoads());
+
+ newEntry.setSystemCyclesUsage(getSystemCpuUsage());
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(
+ String.format("cpu\ncapacities: %f\n loads: %s ; %s ; %s\n stats: %d ; %d ; %d",
+ newEntry.getSystemTotalCpuCycles(),
+ newEntry.getSystemLoadAverages()[0], newEntry.getSystemLoadAverages()[1], newEntry.getSystemLoadAverages()[2],
+ newEntry.getSystemCyclesUsage()[0], newEntry.getSystemCyclesUsage()[1], newEntry.getSystemCyclesUsage()[2]
+ )
+ );
+ }
+ }
+
+ @NotNull
+ private double[] getCpuLoads() {
+ String[] cpuloadString = Script.runSimpleBashScript("cat /proc/loadavg").split(" ");
+ double[] cpuloads = {Double.parseDouble(cpuloadString[0]), Double.parseDouble(cpuloadString[1]), Double.parseDouble(cpuloadString[2])};
+ return cpuloads;
+ }
+
+ private long [] getSystemCpuUsage() {
+ String[] cpustats = Script.runSimpleBashScript("cat /proc/stat | grep \"cpu \" | tr -d \"cpu\"").trim().split(" ");
+ long [] cycleUsage = {Long.parseLong(cpustats[0]) + Long.parseLong(cpustats[1]), Long.parseLong(cpustats[2]), Long.parseLong(cpustats[3])};
+ return cycleUsage;
+ }
+
+ private double getSystemCpuCyclesTotal() {
+ String cpucaps = Script.runSimpleBashScript("cat /proc/cpuinfo | grep \"cpu MHz\" | grep \"cpu MHz\" | cut -f 2 -d : | tr -d ' '| tr '\\n' \" \"");
+ double totalcpucap = 0;
+ for (String cpucap : cpucaps.split(" ")) {
+ totalcpucap += Double.parseDouble(cpucap);
+ }
+ return totalcpucap;
+ }
+
+ private void getFileSystemData(@NotNull ManagementServerHostStatsEntry newEntry) {
+ Set<String> logFileNames = LogUtils.getLogFileNames();
+ StringBuilder logInfoBuilder = new StringBuilder();
+ for (String fileName : logFileNames) {
+ String du = Script.runSimpleBashScript(String.format("du -sh %s | cut -f '1'", fileName));
+ String df = Script.runSimpleBashScript(String.format("df -h %s | grep -v Filesystem | awk '{print \"on disk \" $1 \" mounted on \" $6 \" (\" $5 \" full)\"}'", fileName));
+ logInfoBuilder.append(fileName).append(" using: ").append(du).append('\n').append(df);
+ }
+ newEntry.setLogInfo(logInfoBuilder.toString());
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("log stats:\n" + newEntry.getLogInfo());
+ }
+ }
+
+ private void gatherAllMetrics(ManagementServerHostStatsEntry metricsEntry) {
+ Map<String, Object> metricDetails = new HashMap<>();
+ for (String metricName : METRIC_REGISTRY.getGauges().keySet()) {
+ Object value = getMetric(metricName);
+ metricDetails.put(metricName, value);
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(String.format("Metrics collection '%s'=%s", metricName, value));
+ }
+ // gather what we need from this list
+ extractDetailToField(metricsEntry, metricName, value);
+ }
+ }
+
+ /**
+ * store a value in the local fields of newEntry
+ *
+ * @param metricsEntry the stats info we need to communicate
+ * @param metricName the detail to extract
+ * @param value ;)
+ */
+ private void extractDetailToField(ManagementServerHostStatsEntry metricsEntry, String metricName, Object value) {
+ switch (metricName) {
+ case "memoryheap.used":
+ metricsEntry.setHeapMemoryUsed((Long) value);
+ break;
+ case "memoryheap.max":
+ metricsEntry.setHeapMemoryTotal((Long) value);
+ break;
+ case "threadsblocked.count":
+ metricsEntry.setThreadsBlockedCount((Integer) value);
+ break;
+ case "threadscount":
+ metricsEntry.setThreadsTotalCount((Integer) value);
+ break;
+ case "threadsdaemon.count":
+ metricsEntry.setThreadsDaemonCount((Integer) value);
+ break;
+ case "threadsrunnable.count":
+ metricsEntry.setThreadsRunnableCount((Integer) value);
+ break;
+ case "threadsterminated.count":
+ metricsEntry.setThreadsTerminatedCount((Integer) value);
+ break;
+ case "threadswaiting.count":
+ metricsEntry.setThreadsWaitingCount((Integer) value);
+ break;
+ case "threadsdeadlocks":
+ case "threadsnew.count":
+ case "threadstimed_waiting.count":
+ default:
+ LOGGER.debug(String.format("not storing detail %s, %s", metricName, value));
+ /*
+ * 'buffers.direct.capacity'=8192 type=Long
+ * 'buffers.direct.count'=1 type=Long
+ * 'buffers.direct.used'=8192 type=Long
+ * 'buffers.mapped.capacity'=0 type=Long
+ * 'buffers.mapped.count'=0 type=Long
+ * 'buffers.mapped.used'=0 type=Long
+ * 'gc.G1-Old-Generation.count'=0 type=Long
+ * 'gc.G1-Old-Generation.time'=0 type=Long
+ * 'gc.G1-Young-Generation.count'=36 type=Long
+ * 'gc.G1-Young-Generation.time'=678 type=Long
+ * 'jvm.name'=532601@matah type=String
+ * 'jvm.uptime'=272482 type=Long
+ * 'jvm.vendor'=Red Hat, Inc. OpenJDK 64-Bit Server VM 11.0.12+7 (11) type=String
+ * 'memory.heap.committed'=1200619520 type=Long
+ * 'memory.heap.init'=522190848 type=Long
+ *+ 'memoryheap.max'=4294967296 type=Long
+ * 'memory.heap.usage'=0.06405723094940186 type=Double
+ *+ 'memoryheap.used'=275123712 type=Long
+ * 'memory.non-heap.committed'=217051136 type=Long
+ * 'memory.non-heap.init'=7667712 type=Long
+ * 'memory.non-heap.max'=-1 type=Long
+ * 'memory.non-heap.usage'=-2.11503936E8 type=Double
+ * 'memory.non-heap.used'=211503936 type=Long
+ * 'memory.pools.CodeHeap-'non-nmethods'.usage'=0.3137061403508772 type=Double
+ * 'memory.pools.CodeHeap-'non-profiled-nmethods'.usage'=0.16057488836310319 type=Double
+ * 'memory.pools.CodeHeap-'profiled-nmethods'.usage'=0.3391885643349885 type=Double
+ * 'memory.pools.Compressed-Class-Space.usage'=0.012650594115257263 type=Double
+ * 'memory.pools.G1-Eden-Space.usage'=0.005822416302765648 type=Double
+ * 'memory.pools.G1-Old-Gen.usage'=0.054535746574401855 type=Double
+ * 'memory.pools.G1-Survivor-Space.usage'=1.0 type=Double
+ * 'memory.pools.Metaspace.usage'=0.9765298966718151 type=Double
+ * 'memory.total.committed'=1417670656 type=Long
+ * 'memory.total.init'=529858560 type=Long
+ * 'memory.total.max'=4294967295 type=Long
+ * 'memory.total.used'=486627648 type=Long
+ *+ 'threadsblocked.count'=1 type=Integer
+ *+ 'threadscount'=439 type=Integer
+ *+ 'threadsdaemon.count'=12 type=Integer
+ * 'threadsdeadlocks'=[] type=EmptySet
+ * 'threads.new.count'=0 type=Integer
+ *+ 'threadsrunnable.count'=5 type=Integer
+ *+ 'threadsterminated.count'=0 type=Integer
+ * 'threads.timed_waiting.count'=52 type=Integer
+ *+ 'threadswaiting.count'=381 type=Integer
+ */
+ break;
+ }
+ }
+
+ private Object getMetric(String metricName) {
+ return METRIC_REGISTRY.getGauges().get(metricName).getValue();
+ }
+
+ @Override
+ protected Point createInfluxDbPoint(Object metricsObject) {
+ return null;
+ }
+
+ }
+
+ /**
+ * @return true if there is a usage server installed locally.
+ */
+ protected boolean isUsageLocal() {
+ boolean local = false;
+ String usageInstall = Script.runSimpleBashScript("systemctl status cloudstack-usage | grep \" Loaded:\"");
+ LOGGER.debug(String.format("usage install: %s", usageInstall));
+
+ if (StringUtils.isNotBlank(usageInstall)) {
+ local = usageInstall.contains("enabled");
+ }
+ return local;
+ }
+
+ /**
+ * @return true if the DB endpoint is local to this server
+ */
+ protected boolean isDbLocal() {
+ Properties p = getDbProperties();
+ String configeredHost = p.getProperty("db.cloud.host");
+ String localHost = p.getProperty("cluster.node.IP");
+ // see if these resolve to the same
+ if ("localhost".equals(configeredHost)) return true;
+ if ("127.0.0.1".equals(configeredHost)) return true;
+ if ("::1".equals(configeredHost)) return true;
+ if (StringUtils.isNotBlank(configeredHost) && StringUtils.isNotBlank(localHost) && configeredHost.equals(localHost)) return true;
+ return false;
+ }
+
+ protected Properties getDbProperties() {
+ return DbProperties.getDbProperties();
+ }
+
+ protected class ManagementServerStatusAdministrator implements ClusterManager.StatusAdministrator, ClusterManagerListener {
+ @Override
+ public String newStatus(ClusterServicePdu pdu) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(String.format("StatusUpdate from %s, json: %s", pdu.getSourcePeer(), pdu.getJsonPackage()));
+ }
+
+ ManagementServerHostStatsEntry hostStatsEntry = null;
+ try {
+ hostStatsEntry = gson.fromJson(pdu.getJsonPackage(),new TypeToken<ManagementServerHostStatsEntry>(){}.getType());
+ managementServerHostStats.put(hostStatsEntry.getManagementServerHostUuid(), hostStatsEntry);
+ } catch (JsonParseException e) {
+ LOGGER.error("Exception in decoding of other MS hosts status from : " + pdu.getSourcePeer());
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Exception in decoding of other MS hosts status: ", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onManagementNodeJoined(List<? extends ManagementServerHost> nodeList, long selfNodeId) {
+ // do nothing, but wait for the status to come through
+ }
+
+ @Override
+ public void onManagementNodeLeft(List<? extends ManagementServerHost> nodeList, long selfNodeId) {
+ // remove the status for those ones
+ for (ManagementServerHost node : nodeList) {
+ LOGGER.info(String.format("node %s (%s) at %s (%od) is reported to have left the cluster, invalidating status.",node.getName(), node.getUuid(), node.getServiceIP(), node.getMsid()));
+ managementServerHostStats.remove(node.getUuid());
+ }
+ }
+
+ @Override
+ public void onManagementNodeIsolated() {
+ LOGGER.error(String.format("This management server is reported to be isolated (msid %d", mgmtSrvrId));
+ // not sure if anything should be done now.
+ }
+ }
+
class VmStatsCollector extends AbstractStatsCollector {
@Override
protected void runInContext() {
try {
- s_logger.debug("VmStatsCollector is running...");
+ LOGGER.trace("VmStatsCollector is running...");
SearchCriteria<HostVO> sc = createSearchCriteriaForHostTypeRoutingStateUpAndNotInMaintenance();
List<HostVO> hosts = _hostDao.search(sc, null);
@@ -644,18 +1236,18 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
metrics.clear();
}
} catch (Exception e) {
- s_logger.debug("Failed to get VM stats for host with ID: " + host.getId());
+ LOGGER.debug("Failed to get VM stats for host with ID: " + host.getId());
continue;
}
}
} catch (Throwable t) {
- s_logger.error("Error trying to retrieve VM stats", t);
+ LOGGER.error("Error trying to retrieve VM stats", t);
}
}
@Override
- protected Point creteInfluxDbPoint(Object metricsObject) {
+ protected Point createInfluxDbPoint(Object metricsObject) {
return createInfluxDbPointForVmMetrics(metricsObject);
}
}
@@ -754,9 +1346,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
if (scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
//Check for ownership
//msHost in UP state with min id should run the job
- ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+ ManagementServerHostVO msHost = managementServerHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
if (msHost == null || (msHost.getMsid() != mgmtSrvrId)) {
- s_logger.debug("Skipping aggregate disk stats update");
+ LOGGER.debug("Skipping aggregate disk stats update");
scanLock.unlock();
return;
}
@@ -776,17 +1368,17 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
_vmDiskStatsDao.update(stat.getId(), stat);
}
}
- s_logger.debug("Successfully updated aggregate vm disk stats");
+ LOGGER.debug("Successfully updated aggregate vm disk stats");
}
});
} catch (Exception e) {
- s_logger.debug("Failed to update aggregate disk stats", e);
+ LOGGER.debug("Failed to update aggregate disk stats", e);
} finally {
scanLock.unlock();
}
}
} catch (Exception e) {
- s_logger.debug("Exception while trying to acquire disk stats lock", e);
+ LOGGER.debug("Exception while trying to acquire disk stats lock", e);
} finally {
scanLock.releaseRef();
}
@@ -798,13 +1390,13 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
protected void runInContext() {
//Check for ownership
//msHost in UP state with min id should run the job
- ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+ ManagementServerHostVO msHost = managementServerHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
if (msHost == null || (msHost.getMsid() != mgmtSrvrId)) {
- s_logger.debug("Skipping collect vm disk stats from hosts");
+ LOGGER.debug("Skipping collect vm disk stats from hosts");
return;
}
// collect the vm disk statistics(total) from hypervisor. added by weizhou, 2013.03.
- s_logger.debug("VmDiskStatsTask is running...");
+ LOGGER.debug("VmDiskStatsTask is running...");
SearchCriteria<HostVO> sc = createSearchCriteriaForHostTypeRoutingStateUpAndNotInMaintenance();
sc.addAnd("hypervisorType", SearchCriteria.Op.IN, HypervisorType.KVM, HypervisorType.VMware);
@@ -846,26 +1438,26 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
VmDiskStatisticsVO vmDiskStat_lock = _vmDiskStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), vmId, volume.getId());
if (areAllDiskStatsZero(vmDiskStat)) {
- s_logger.debug("IO/bytes read and write are all 0. Not updating vm_disk_statistics");
+ LOGGER.debug("IO/bytes read and write are all 0. Not updating vm_disk_statistics");
continue;
}
if (vmDiskStat_lock == null) {
- s_logger.warn("unable to find vm disk stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()
+ LOGGER.warn("unable to find vm disk stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()
+ " and volumeId:" + volume.getId());
continue;
}
if (isCurrentVmDiskStatsDifferentFromPrevious(previousVmDiskStats, vmDiskStat_lock)) {
- s_logger.debug("vm disk stats changed from the time GetVmDiskStatsCommand was sent. " + "Ignoring current answer. Host: " + host.getName()
+ LOGGER.debug("vm disk stats changed from the time GetVmDiskStatsCommand was sent. " + "Ignoring current answer. Host: " + host.getName()
+ " . VM: " + vmDiskStat.getVmName() + " Read(Bytes): " + toHumanReadableSize(vmDiskStat.getBytesRead()) + " write(Bytes): " + toHumanReadableSize(vmDiskStat.getBytesWrite())
+ " Read(IO): " + toHumanReadableSize(vmDiskStat.getIORead()) + " write(IO): " + toHumanReadableSize(vmDiskStat.getIOWrite()));
continue;
}
if (vmDiskStat_lock.getCurrentBytesRead() > vmDiskStat.getBytesRead()) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Read # of bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Read # of bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ host.getName() + " . VM: " + vmDiskStat.getVmName() + " Reported: " + toHumanReadableSize(vmDiskStat.getBytesRead()) + " Stored: "
+ vmDiskStat_lock.getCurrentBytesRead());
}
@@ -873,8 +1465,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
vmDiskStat_lock.setCurrentBytesRead(vmDiskStat.getBytesRead());
if (vmDiskStat_lock.getCurrentBytesWrite() > vmDiskStat.getBytesWrite()) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Write # of bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Write # of bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ host.getName() + " . VM: " + vmDiskStat.getVmName() + " Reported: " + toHumanReadableSize(vmDiskStat.getBytesWrite()) + " Stored: "
+ toHumanReadableSize(vmDiskStat_lock.getCurrentBytesWrite()));
}
@@ -882,8 +1474,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
vmDiskStat_lock.setCurrentBytesWrite(vmDiskStat.getBytesWrite());
if (vmDiskStat_lock.getCurrentIORead() > vmDiskStat.getIORead()) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Read # of IO that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Read # of IO that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ host.getName() + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getIORead() + " Stored: "
+ vmDiskStat_lock.getCurrentIORead());
}
@@ -891,8 +1483,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
vmDiskStat_lock.setCurrentIORead(vmDiskStat.getIORead());
if (vmDiskStat_lock.getCurrentIOWrite() > vmDiskStat.getIOWrite()) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Write # of IO that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Write # of IO that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ host.getName() + " . VM: " + vmDiskStat.getVmName() + " Reported: " + vmDiskStat.getIOWrite() + " Stored: "
+ vmDiskStat_lock.getCurrentIOWrite());
}
@@ -914,7 +1506,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
});
} catch (Exception e) {
- s_logger.warn(String.format("Error while collecting vm disk stats from host %s : ", host.getName()), e);
+ LOGGER.warn(String.format("Error while collecting vm disk stats from host %s : ", host.getName()), e);
}
}
}
@@ -925,13 +1517,13 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
protected void runInContext() {
//Check for ownership
//msHost in UP state with min id should run the job
- ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+ ManagementServerHostVO msHost = managementServerHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
if (msHost == null || (msHost.getMsid() != mgmtSrvrId)) {
- s_logger.debug("Skipping collect vm network stats from hosts");
+ LOGGER.debug("Skipping collect vm network stats from hosts");
return;
}
// collect the vm network statistics(total) from hypervisor
- s_logger.debug("VmNetworkStatsTask is running...");
+ LOGGER.debug("VmNetworkStatsTask is running...");
SearchCriteria<HostVO> sc = createSearchCriteriaForHostTypeRoutingStateUpAndNotInMaintenance();
List<HostVO> hosts = _hostDao.search(sc, null);
@@ -960,10 +1552,10 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
continue;
UserVmVO userVm = _userVmDao.findById(vmId);
if (userVm == null) {
- s_logger.debug("Cannot find uservm with id: " + vmId + " , continue");
+ LOGGER.debug("Cannot find uservm with id: " + vmId + " , continue");
continue;
}
- s_logger.debug("Now we are updating the user_statistics table for VM: " + userVm.getInstanceName()
+ LOGGER.debug("Now we are updating the user_statistics table for VM: " + userVm.getInstanceName()
+ " after collecting vm network statistics from host: " + host.getName());
for (VmNetworkStatsEntry vmNetworkStat : vmNetworkStats) {
SearchCriteria<NicVO> sc_nic = _nicDao.createSearchCriteria();
@@ -983,27 +1575,27 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
nic.getIPv4Address(), vmId, "UserVm");
if ((vmNetworkStat.getBytesSent() == 0) && (vmNetworkStat.getBytesReceived() == 0)) {
- s_logger.debug("bytes sent and received are all 0. Not updating user_statistics");
+ LOGGER.debug("bytes sent and received are all 0. Not updating user_statistics");
continue;
}
if (vmNetworkStat_lock == null) {
- s_logger.warn("unable to find vm network stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()
+ LOGGER.warn("unable to find vm network stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()
+ " and nicId:" + nic.getId());
continue;
}
if (previousvmNetworkStats != null && ((previousvmNetworkStats.getCurrentBytesSent() != vmNetworkStat_lock.getCurrentBytesSent())
|| (previousvmNetworkStats.getCurrentBytesReceived() != vmNetworkStat_lock.getCurrentBytesReceived()))) {
- s_logger.debug("vm network stats changed from the time GetNmNetworkStatsCommand was sent. " + "Ignoring current answer. Host: "
+ LOGGER.debug("vm network stats changed from the time GetNmNetworkStatsCommand was sent. " + "Ignoring current answer. Host: "
+ host.getName() + " . VM: " + vmNetworkStat.getVmName() + " Sent(Bytes): " + vmNetworkStat.getBytesSent() + " Received(Bytes): "
+ vmNetworkStat.getBytesReceived());
continue;
}
if (vmNetworkStat_lock.getCurrentBytesSent() > vmNetworkStat.getBytesSent()) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Sent # of bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Sent # of bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ host.getName() + " . VM: " + vmNetworkStat.getVmName() + " Reported: " + toHumanReadableSize(vmNetworkStat.getBytesSent()) + " Stored: "
+ toHumanReadableSize(vmNetworkStat_lock.getCurrentBytesSent()));
}
@@ -1012,8 +1604,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
vmNetworkStat_lock.setCurrentBytesSent(vmNetworkStat.getBytesSent());
if (vmNetworkStat_lock.getCurrentBytesReceived() > vmNetworkStat.getBytesReceived()) {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Received # of bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Received # of bytes that's less than the last one. " + "Assuming something went wrong and persisting it. Host: "
+ host.getName() + " . VM: " + vmNetworkStat.getVmName() + " Reported: " + toHumanReadableSize(vmNetworkStat.getBytesReceived()) + " Stored: "
+ toHumanReadableSize(vmNetworkStat_lock.getCurrentBytesReceived()));
}
@@ -1033,7 +1625,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
});
} catch (Exception e) {
- s_logger.warn(String.format("Error while collecting vm network stats from host %s : ", host.getName()), e);
+ LOGGER.warn(String.format("Error while collecting vm network stats from host %s : ", host.getName()), e);
}
}
}
@@ -1049,7 +1641,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
List<VolumeVO> volumes = _volsDao.findByPoolId(pool.getId(), null);
for (VolumeVO volume : volumes) {
if (volume.getFormat() != ImageFormat.QCOW2 && volume.getFormat() != ImageFormat.VHD && volume.getFormat() != ImageFormat.OVA && (volume.getFormat() != ImageFormat.RAW || pool.getPoolType() != Storage.StoragePoolType.PowerFlex)) {
- s_logger.warn("Volume stats not implemented for this format type " + volume.getFormat());
+ LOGGER.warn("Volume stats not implemented for this format type " + volume.getFormat());
break;
}
}
@@ -1075,12 +1667,12 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
}
} catch (Exception e) {
- s_logger.warn("Failed to get volume stats for cluster with ID: " + pool.getClusterId(), e);
+ LOGGER.warn("Failed to get volume stats for cluster with ID: " + pool.getClusterId(), e);
continue;
}
}
} catch (Throwable t) {
- s_logger.error("Error trying to retrieve volume stats", t);
+ LOGGER.error("Error trying to retrieve volume stats", t);
}
}
}
@@ -1096,8 +1688,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
@Override
protected void runInContext() {
try {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("StorageCollector is running...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("StorageCollector is running...");
}
List<DataStore> stores = _dataStoreMgr.listImageStores();
@@ -1111,14 +1703,14 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
GetStorageStatsCommand command = new GetStorageStatsCommand(store.getTO(), nfsVersion);
EndPoint ssAhost = _epSelector.select(store);
if (ssAhost == null) {
- s_logger.debug("There is no secondary storage VM for secondary storage host " + store.getName());
+ LOGGER.debug("There is no secondary storage VM for secondary storage host " + store.getName());
continue;
}
long storeId = store.getId();
Answer answer = ssAhost.sendMessage(command);
if (answer != null && answer.getResult()) {
storageStats.put(storeId, (StorageStats)answer);
- s_logger.trace("HostId: " + storeId + " Used: " + toHumanReadableSize(((StorageStats)answer).getByteUsed()) + " Total Available: " + toHumanReadableSize(((StorageStats)answer).getCapacityBytes()));
+ LOGGER.trace("HostId: " + storeId + " Used: " + toHumanReadableSize(((StorageStats)answer).getByteUsed()) + " Total Available: " + toHumanReadableSize(((StorageStats)answer).getCapacityBytes()));
}
}
_storageStats = storageStats;
@@ -1144,7 +1736,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
pool.setCapacityBytes(((StorageStats)answer).getCapacityBytes());
poolNeedsUpdating = true;
} else {
- s_logger.warn("Not setting capacity bytes, received " + ((StorageStats)answer).getCapacityBytes() + " capacity for pool ID " + poolId);
+ LOGGER.warn("Not setting capacity bytes, received " + ((StorageStats)answer).getCapacityBytes() + " capacity for pool ID " + poolId);
}
}
if (pool.getUsedBytes() != ((StorageStats)answer).getByteUsed() && (pool.getStorageProviderName().equalsIgnoreCase(DataStoreProvider.DEFAULT_PRIMARY) || _storageManager.canPoolProvideStorageStats(pool))) {
@@ -1157,14 +1749,14 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
}
} catch (StorageUnavailableException e) {
- s_logger.info("Unable to reach " + pool, e);
+ LOGGER.info("Unable to reach " + pool, e);
} catch (Exception e) {
- s_logger.warn("Unable to get stats for " + pool, e);
+ LOGGER.warn("Unable to get stats for " + pool, e);
}
}
_storagePoolStats = storagePoolStats;
} catch (Throwable t) {
- s_logger.error("Error trying to retrieve storage stats", t);
+ LOGGER.error("Error trying to retrieve storage stats", t);
}
}
}
@@ -1173,8 +1765,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
@Override
protected void runInContext() {
try {
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("AutoScaling Monitor is running...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("AutoScaling Monitor is running...");
}
// list all AS VMGroups
List<AutoScaleVmGroupVO> asGroups = _asGroupDao.listAll();
@@ -1199,9 +1791,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
asGroup.setLastInterval(new Date());
_asGroupDao.persist(asGroup);
- // collect RRDs data for this group
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("[AutoScale] Collecting RRDs data...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("[AutoScale] Collecting RRDs data...");
}
Map<String, String> params = new HashMap<String, String>();
List<AutoScaleVmGroupVmMapVO> asGroupVmVOs = _asGroupVmDao.listByGroup(asGroup.getId());
@@ -1242,10 +1833,10 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
try {
Answer answer = _agentMgr.send(receiveHost, perfMon);
if (answer == null || !answer.getResult()) {
- s_logger.debug("Failed to send data to node !");
+ LOGGER.debug("Failed to send data to node !");
} else {
String result = answer.getDetails();
- s_logger.debug("[AutoScale] RRDs collection answer: " + result);
+ LOGGER.debug("[AutoScale] RRDs collection answer: " + result);
HashMap<Long, Double> avgCounter = new HashMap<Long, Double>();
// extract data
@@ -1291,7 +1882,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
String scaleAction = getAutoscaleAction(avgCounter, asGroup.getId(), currentVM, params);
if (scaleAction != null) {
- s_logger.debug("[AutoScale] Doing scale action: " + scaleAction + " for group " + asGroup.getId());
+ LOGGER.debug("[AutoScale] Doing scale action: " + scaleAction + " for group " + asGroup.getId());
if (scaleAction.equals("scaleup")) {
_asManager.doScaleUp(asGroup.getId(), 1);
} else {
@@ -1309,7 +1900,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
} catch (Throwable t) {
- s_logger.error("Error trying to monitor autoscaling", t);
+ LOGGER.error("Error trying to monitor autoscaling", t);
}
}
@@ -1452,7 +2043,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
* This class allows to writing metrics in InfluxDB for the table that matches the Collector extending it.
* Thus, VmStatsCollector and HostCollector can use same method to write on different measures (host_stats or vm_stats table).
*/
- abstract class AbstractStatsCollector extends ManagedContextRunnable {
+ abstract class AbstractStatsCollector extends ManagedContextRunnable {
/**
* Sends metrics to influxdb host. This method supports both VM and Host metrics
*/
@@ -1468,10 +2059,10 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
Collection<Object> metricsObjects = metrics.values();
List<Point> points = new ArrayList<>();
- s_logger.debug(String.format("Sending stats to %s host %s:%s", externalStatsType, externalStatsHost, externalStatsPort));
+ LOGGER.debug(String.format("Sending stats to %s host %s:%s", externalStatsType, externalStatsHost, externalStatsPort));
for (Object metricsObject : metricsObjects) {
- Point vmPoint = creteInfluxDbPoint(metricsObject);
+ Point vmPoint = createInfluxDbPoint(metricsObject);
points.add(vmPoint);
}
writeBatches(influxDbConnection, databaseName, points);
@@ -1483,7 +2074,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
/**
* Creates a InfluxDB point for the given stats collector (VmStatsCollector, or HostCollector).
*/
- protected abstract Point creteInfluxDbPoint(Object metricsObject);
+ protected abstract Point createInfluxDbPoint(Object metricsObject);
}
public boolean imageStoreHasEnoughCapacity(DataStore imageStore) {
@@ -1495,7 +2086,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
StorageStats imageStoreStats = _storageStats.get(imageStoreId);
if (imageStoreStats == null) {
- s_logger.debug(String.format("Stats for image store [%s] not found.", imageStoreId));
+ LOGGER.debug(String.format("Stats for image store [%s] not found.", imageStoreId));
return false;
}
@@ -1505,13 +2096,13 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
String readableTotalCapacity = FileUtils.byteCountToDisplaySize((long) totalCapacity);
String readableUsedCapacity = FileUtils.byteCountToDisplaySize((long) usedCapacity);
- s_logger.debug(String.format("Verifying image storage [%s]. Capacity: total=[%s], used=[%s], threshold=[%s%%].", imageStoreId, readableTotalCapacity, readableUsedCapacity, threshold * 100));
+ LOGGER.debug(String.format("Verifying image storage [%s]. Capacity: total=[%s], used=[%s], threshold=[%s%%].", imageStoreId, readableTotalCapacity, readableUsedCapacity, threshold * 100));
if (usedCapacity / totalCapacity <= threshold) {
return true;
}
- s_logger.warn(String.format("Image storage [%s] has not enough capacity. Capacity: total=[%s], used=[%s], threshold=[%s%%].", imageStoreId, readableTotalCapacity, readableUsedCapacity, threshold * 100));
+ LOGGER.warn(String.format("Image storage [%s] has not enough capacity. Capacity: total=[%s], used=[%s], threshold=[%s%%].", imageStoreId, readableTotalCapacity, readableUsedCapacity, threshold * 100));
return false;
}
@@ -1538,12 +2129,12 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
* Sends VMs metrics to the configured graphite host.
*/
protected void sendVmMetricsToGraphiteHost(Map<Object, Object> metrics, HostVO host) {
- s_logger.debug(String.format("Sending VmStats of host %s to %s host %s:%s", host.getId(), externalStatsType, externalStatsHost, externalStatsPort));
+ LOGGER.debug(String.format("Sending VmStats of host %s to %s host %s:%s", host.getId(), externalStatsType, externalStatsHost, externalStatsPort));
try {
GraphiteClient g = new GraphiteClient(externalStatsHost, externalStatsPort);
g.sendMetrics(metrics);
} catch (GraphiteException e) {
- s_logger.debug("Failed sending VmStats to Graphite host " + externalStatsHost + ":" + externalStatsPort + ": " + e.getMessage());
+ LOGGER.debug("Failed sending VmStats to Graphite host " + externalStatsHost + ":" + externalStatsPort + ": " + e.getMessage());
}
}
@@ -1581,7 +2172,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
statsForCurrentIteration.getDiskWriteKBs(), statsForCurrentIteration.getDiskReadIOs(), statsForCurrentIteration.getDiskWriteIOs(),
statsForCurrentIteration.getEntityType());
VmStatsVO vmStatsVO = new VmStatsVO(statsForCurrentIteration.getVmId(), msId, timestamp, gson.toJson(vmStats));
- s_logger.trace(String.format("Recording VM stats: [%s].", vmStatsVO.toString()));
+ LOGGER.trace(String.format("Recording VM stats: [%s].", vmStatsVO.toString()));
vmStatsDao.persist(vmStatsVO);
}
@@ -1592,11 +2183,11 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
protected void cleanUpVirtualMachineStats() {
Integer maxRetentionTime = vmStatsMaxRetentionTime.value();
if (maxRetentionTime <= 0) {
- s_logger.debug(String.format("Skipping VM stats cleanup. The [%s] parameter [%s] is set to 0 or less than 0.",
+ LOGGER.debug(String.format("Skipping VM stats cleanup. The [%s] parameter [%s] is set to 0 or less than 0.",
vmStatsMaxRetentionTime.scope(), vmStatsMaxRetentionTime.toString()));
return;
}
- s_logger.trace("Removing older VM stats records.");
+ LOGGER.trace("Removing older VM stats records.");
Date now = new Date();
Date limit = DateUtils.addMinutes(now, -maxRetentionTime);
vmStatsDao.removeAllByTimestampLessThan(limit);
@@ -1735,6 +2326,15 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
return _hostStats.get(hostId);
}
+ public Map<String, Object> getDbStats() {
+ return dbStats;
+ }
+
+
+ public ManagementServerHostStats getManagementServerHostStats(String managementServerUuid) {
+ return managementServerHostStats.get(managementServerUuid);
+ }
+
public StorageStats getStoragePoolStats(long id) {
return _storagePoolStats.get(id);
}
@@ -1747,7 +2347,11 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {vmDiskStatsInterval, vmDiskStatsIntervalMin, vmNetworkStatsInterval, vmNetworkStatsIntervalMin, StatsTimeout, statsOutputUri,
- vmStatsIncrementMetrics, vmStatsMaxRetentionTime};
+ vmStatsIncrementMetrics, vmStatsMaxRetentionTime,
+ VM_STATS_INCREMENT_METRICS_IN_MEMORY,
+ MANAGEMENT_SERVER_STATUS_COLLECTION_INTERVAL,
+ DATABASE_SERVER_STATUS_COLLECTION_INTERVAL,
+ DATABASE_SERVER_LOAD_HISTORY_RETENTION_NUMBER};
}
public double getImageStoreCapacityThreshold() {
diff --git a/server/src/test/async-job-component.xml b/server/src/test/async-job-component.xml
index fbe1015cbe..413194c671 100644
--- a/server/src/test/async-job-component.xml
+++ b/server/src/test/async-job-component.xml
@@ -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" />
diff --git a/server/src/test/java/com/cloud/server/StatsCollectorTest.java b/server/src/test/java/com/cloud/server/StatsCollectorTest.java
index f32b05e4dd..206b6b81f7 100644
--- a/server/src/test/java/com/cloud/server/StatsCollectorTest.java
+++ b/server/src/test/java/com/cloud/server/StatsCollectorTest.java
@@ -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());
+ }
}
diff --git a/test/integration/smoke/test_metrics_api.py b/test/integration/smoke/test_metrics_api.py
index 7cd09b44c7..e870dadee8 100644
--- a/test/integration/smoke/test_metrics_api.py
+++ b/test/integration/smoke/test_metrics_api.py
@@ -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
+
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 2fee8c8e3d..e00e7b3c2d 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -1,8 +1,32430 @@
{
"name": "cloudstack-ui",
"version": "1.0.0",
- "lockfileVersion": 1,
+ "lockfileVersion": 2,
"requires": true,
+ "packages": {
+ "": {
+ "name": "cloudstack-ui",
+ "version": "1.0.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@fortawesome/fontawesome-svg-core": "^1.2.34",
+ "@fortawesome/free-brands-svg-icons": "^5.15.2",
+ "@fortawesome/free-solid-svg-icons": "^5.15.2",
+ "@fortawesome/vue-fontawesome": "^2.0.2",
+ "ant-design-vue": "~1.7.3",
+ "antd-theme-webpack-plugin": "^1.3.9",
+ "axios": "^0.21.1",
+ "babel-plugin-require-context-hook": "^1.0.0",
+ "core-js": "^3.6.5",
+ "enquire.js": "^2.1.6",
+ "js-cookie": "^2.2.1",
+ "lodash": "^4.17.15",
+ "md5": "^2.2.1",
+ "moment": "^2.26.0",
+ "npm-check-updates": "^6.0.1",
+ "nprogress": "^0.2.0",
+ "viser-vue": "^2.4.8",
+ "vue": "^2.6.12",
+ "vue-clipboard2": "^0.3.1",
+ "vue-cropper": "0.5.6",
+ "vue-i18n": "^8.22.4",
+ "vue-ls": "^3.2.2",
+ "vue-router": "^3.5.1",
+ "vue-svg-component-runtime": "^1.0.1",
+ "vuedraggable": "^2.24.3",
+ "vuex": "^3.6.2"
+ },
+ "devDependencies": {
+ "@vue/cli": "^4.4.1",
+ "@vue/cli-plugin-babel": "^4.4.1",
+ "@vue/cli-plugin-eslint": "^4.4.1",
+ "@vue/cli-plugin-unit-jest": "^4.4.1",
+ "@vue/cli-service": "^4.4.1",
+ "@vue/eslint-config-standard": "^5.1.2",
+ "@vue/test-utils": "^1.0.3",
+ "babel-core": "7.0.0-bridge.0",
+ "babel-eslint": "^10.0.3",
+ "babel-jest": "^25.1.0",
+ "babel-plugin-import": "^1.13.0",
+ "eslint": "^6.8.0",
+ "eslint-plugin-html": "^6.0.2",
+ "eslint-plugin-import": "^2.20.2",
+ "eslint-plugin-node": "^11.1.0",
+ "eslint-plugin-promise": "^4.2.1",
+ "eslint-plugin-standard": "^4.0.1",
+ "eslint-plugin-vue": "^6.2.2",
+ "less": "^3.11.1",
+ "less-loader": "^5.0.0",
+ "node-sass": "^4.13.1",
+ "sass-loader": "^8.0.2",
+ "uglifyjs-webpack-plugin": "^2.2.0",
+ "vue-cli-plugin-i18n": "^1.0.1",
+ "vue-svg-icon-loader": "^2.1.1",
+ "vue-template-compiler": "^2.6.12",
+ "webpack": "^4.43.0"
+ }
+ },
+ "node_modules/@akryum/winattr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@akryum/winattr/-/winattr-3.0.0.tgz",
+ "integrity": "sha512-t4WmWoGV9gyzypwG3y3JlcK2t8fKLtvzBA7xEoFTj9SMPvOuLsf13uh4ikK0RRaaa9RPPWLgFUdOyIRaQvCpwQ==",
+ "dev": true,
+ "dependencies": {
+ "fswin": "^2.17.1227"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@ant-design/colors": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz",
+ "integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==",
+ "dependencies": {
+ "tinycolor2": "^1.4.1"
+ }
+ },
+ "node_modules/@ant-design/icons": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
+ "integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
+ },
+ "node_modules/@ant-design/icons-vue": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-2.0.0.tgz",
+ "integrity": "sha512-2c0QQE5hL4N48k5NkPG5sdpMl9YnvyNhf0U7YkdZYDlLnspoRU7vIA0UK9eHBs6OpFLcJB6o8eJrIl2ajBskPg==",
+ "dependencies": {
+ "@ant-design/colors": "^3.1.0",
+ "babel-runtime": "^6.26.0"
+ },
+ "peerDependencies": {
+ "@ant-design/icons": "^2.0.0",
+ "vue": ">=2.5.0",
+ "vue-template-compiler": ">=2.5.0"
+ }
+ },
+ "node_modules/@antv/adjust": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@antv/adjust/-/adjust-0.1.1.tgz",
+ "integrity": "sha512-9FaMOyBlM4AgoRL0b5o0VhEKAYkexBNUrxV8XmpHU/9NBPJONBOB/NZUlQDqxtLItrt91tCfbAuMQmF529UX2Q==",
+ "dependencies": {
+ "@antv/util": "~1.3.1"
+ }
+ },
+ "node_modules/@antv/attr": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@antv/attr/-/attr-0.1.2.tgz",
+ "integrity": "sha512-QXjP+T2I+pJQcwZx1oCA4tipG43vgeCeKcGGKahlcxb71OBAzjJZm1QbF4frKXcnOqRkxVXtCr70X9TRair3Ew==",
+ "dependencies": {
+ "@antv/util": "~1.3.1"
+ }
+ },
+ "node_modules/@antv/component": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.3.9.tgz",
+ "integrity": "sha512-Knh/Nq0S8UkTfZj4SL7XizagTfXYqjFAYIqFtOmUaKpRMgccUi7p1oA7fJdNPGktkndljy6fUmCWocEeBXRS2g==",
+ "dependencies": {
+ "@antv/attr": "~0.1.2",
+ "@antv/g": "~3.3.5",
+ "@antv/util": "~1.3.1",
+ "wolfy87-eventemitter": "~5.1.0"
+ }
+ },
+ "node_modules/@antv/component/node_modules/@antv/g": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/@antv/g/-/g-3.3.6.tgz",
+ "integrity": "sha512-2GtyTz++s0BbN6s0ZL2/nrqGYCkd52pVoNH92YkrTdTOvpO6Z4DNoo6jGVgZdPX6Nzwli6yduC8MinVAhE8X6g==",
+ "dependencies": {
+ "@antv/gl-matrix": "~2.7.1",
+ "@antv/util": "~1.3.1",
+ "d3-ease": "~1.0.3",
+ "d3-interpolate": "~1.1.5",
+ "d3-timer": "~1.0.6",
+ "wolfy87-eventemitter": "~5.1.0"
+ }
+ },
+ "node_modules/@antv/coord": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.1.0.tgz",
+ "integrity": "sha512-W1R8h3Jfb3AfMBVfCreFPMVetgEYuwHBIGn0+d3EgYXe2ckOF8XWjkpGF1fZhOMHREMr+Gt27NGiQh8yBdLUgg==",
+ "dependencies": {
+ "@antv/util": "~1.3.1"
+ }
+ },
+ "node_modules/@antv/g": {
+ "version": "3.4.10",
+ "resolved": "https://registry.npmjs.org/@antv/g/-/g-3.4.10.tgz",
+ "integrity": "sha512-pKy/L1SyRBsXuujdkggqrdBA0/ciAgHiArYBdIJsxHRxCneUP01wGwHdGfDayh2+S0gcSBHynjhoEahsaZaLkw==",
+ "dependencies": {
+ "@antv/gl-matrix": "~2.7.1",
+ "@antv/util": "~1.3.1",
+ "d3-ease": "~1.0.3",
+ "d3-interpolate": "~1.1.5",
+ "d3-timer": "~1.0.6",
+ "detect-browser": "^5.1.0"
+ }
+ },
+ "node_modules/@antv/g2": {
+ "version": "3.5.17",
+ "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-3.5.17.tgz",
+ "integrity": "sha512-gOjfA6pwXYEC5mrLbvg1kA3jZI5J5T2kQeGse+iBBsNc1Vje7zs9G+BleUaI4MLXSnqwhsj/ohfkP7d+h4ArNg==",
+ "dependencies": {
+ "@antv/adjust": "~0.1.0",
+ "@antv/attr": "~0.1.2",
+ "@antv/component": "~0.3.3",
+ "@antv/coord": "~0.1.0",
+ "@antv/g": "~3.4.10",
+ "@antv/scale": "~0.1.1",
+ "@antv/util": "~1.3.1",
+ "venn.js": "~0.2.20",
+ "wolfy87-eventemitter": "~5.1.0"
+ }
+ },
+ "node_modules/@antv/g2-brush": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@antv/g2-brush/-/g2-brush-0.0.2.tgz",
+ "integrity": "sha512-7O9szwem19nmEgReXhFB8kVLRaz8J5MHvrzDSDY36YaBOaHSWRGHnvYt2KkkPqgWtHtLY1srssk4X/UmP5govA=="
+ },
+ "node_modules/@antv/g2-plugin-slider": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@antv/g2-plugin-slider/-/g2-plugin-slider-2.1.1.tgz",
+ "integrity": "sha512-nB678VEGG3FkrvkDDFADAKjLQIeXzITEYqey5oeOpbf0vT5jOa55lQDyJDZ79cK8PmU/Hz6VPeSb3CNQBA+/FQ==",
+ "peerDependencies": {
+ "@antv/g2": ">=3.2.8"
+ }
+ },
+ "node_modules/@antv/gl-matrix": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/@antv/gl-matrix/-/gl-matrix-2.7.1.tgz",
+ "integrity": "sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q=="
+ },
+ "node_modules/@antv/scale": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.1.5.tgz",
+ "integrity": "sha512-7RAu4iH5+Hk21h6+aBMiDTfmLf4IibK2SWjx/+E4f4AXRpqucO+8u7IbZdFkakAWxvqhJtN3oePJuTKqOMcmlg==",
+ "dependencies": {
+ "@antv/util": "~1.3.1",
+ "fecha": "~2.3.3"
+ }
+ },
+ "node_modules/@antv/util": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@antv/util/-/util-1.3.1.tgz",
+ "integrity": "sha512-cbUta0hIJrKEaW3eKoGarz3Ita+9qUPF2YzTj8A6wds/nNiy20G26ztIWHU+5ThLc13B1n5Ik52LbaCaeg9enA==",
+ "dependencies": {
+ "@antv/gl-matrix": "^2.7.1"
+ }
+ },
+ "node_modules/@apollo/federation": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@apollo/federation/-/federation-0.17.0.tgz",
+ "integrity": "sha512-vSW/M8+SGdu5xALsA/RL37GgB+wNFZpXCyPAcg3b68c8x7uoQHgYwqwUu7D+GnAGeOpDUrNnFPdKAYW7elYkyQ==",
+ "dev": true,
+ "dependencies": {
+ "apollo-graphql": "^0.4.0",
+ "apollo-server-env": "^2.4.5",
+ "core-js": "^3.4.0",
+ "lodash.xorby": "^4.7.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "peerDependencies": {
+ "graphql": "^14.5.0 || ^15.0.0"
+ }
+ },
+ "node_modules/@apollo/federation/node_modules/apollo-graphql": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.4.5.tgz",
+ "integrity": "sha512-0qa7UOoq7E71kBYE7idi6mNQhHLVdMEDInWk6TNw3KsSWZE2/I68gARP84Mj+paFTO5NYuw1Dht66PVX76Cc2w==",
+ "dev": true,
+ "dependencies": {
+ "apollo-env": "^0.6.5",
+ "lodash.sortby": "^4.7.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "graphql": "^14.2.1"
+ }
+ },
+ "node_modules/@apollo/protobufjs": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.0.4.tgz",
+ "integrity": "sha512-EE3zx+/D/wur/JiLp6VCiw1iYdyy1lCJMf8CGPkLeDt5QJrN4N8tKFx33Ah4V30AUQzMk7Uz4IXKZ1LOj124gA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/long": "^4.0.0",
+ "@types/node": "^10.1.0",
+ "long": "^4.0.0"
+ },
+ "bin": {
+ "apollo-pbjs": "bin/pbjs",
+ "apollo-pbts": "bin/pbts"
+ }
+ },
+ "node_modules/@apollo/protobufjs/node_modules/@types/node": {
+ "version": "10.17.28",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.28.tgz",
+ "integrity": "sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ==",
+ "dev": true
+ },
+ "node_modules/@apollographql/apollo-tools": {
+ "version": "0.4.8",
+ "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.4.8.tgz",
+ "integrity": "sha512-W2+HB8Y7ifowcf3YyPHgDI05izyRtOeZ4MqIr7LbTArtmJ0ZHULWpn84SGMW7NAvTV1tFExpHlveHhnXuJfuGA==",
+ "dev": true,
+ "dependencies": {
+ "apollo-env": "^0.6.5"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/@apollographql/graphql-language-service-interface": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-interface/-/graphql-language-service-interface-2.0.2.tgz",
+ "integrity": "sha512-28wePK0hlIVjgmvMXMAUq8qRSjz9O+6lqFp4PzOTHtfJfSsjVe9EfjF98zTpHsTgT3HcOxmbqDZZy8jlXtOqEA==",
+ "dev": true,
+ "dependencies": {
+ "@apollographql/graphql-language-service-parser": "^2.0.0",
+ "@apollographql/graphql-language-service-types": "^2.0.0",
+ "@apollographql/graphql-language-service-utils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "graphql": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0"
+ }
+ },
+ "node_modules/@apollographql/graphql-language-service-parser": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-parser/-/graphql-language-service-parser-2.0.2.tgz",
+ "integrity": "sha512-rpTPrEJu1PMaRQxz5P8BZWsixNNhYloS0H0dwTxNBuE3qctbARvR7o8UCKLsmKgTbo+cz3T3a6IAsWlkHgMWGg==",
+ "dev": true,
+ "dependencies": {
+ "@apollographql/graphql-language-service-types": "^2.0.0"
+ },
+ "peerDependencies": {
+ "graphql": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0"
+ }
+ },
+ "node_modules/@apollographql/graphql-language-service-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-types/-/graphql-language-service-types-2.0.2.tgz",
+ "integrity": "sha512-vE+Dz8pG+Xa1Z2nMl82LoO66lQ6JqBUjaXqLDvS3eMjvA3N4hf+YUDOWfPdNZ0zjhHhHXzUIIZCkax6bXfFbzQ==",
+ "dev": true,
+ "peerDependencies": {
+ "graphql": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0"
+ }
+ },
+ "node_modules/@apollographql/graphql-language-service-utils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-utils/-/graphql-language-service-utils-2.0.2.tgz",
+ "integrity": "sha512-fDj5rWlTi/czvUS5t7V7I45Ai6bOO3Z7JARYj21Y2xxfbRGtJi6h8FvLX0N/EbzQgo/fiZc/HAhtfwn+OCjD7A==",
+ "dev": true,
+ "dependencies": {
+ "@apollographql/graphql-language-service-types": "^2.0.0"
+ },
+ "peerDependencies": {
+ "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0"
+ }
+ },
+ "node_modules/@apollographql/graphql-playground-html": {
+ "version": "1.6.26",
+ "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz",
+ "integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==",
+ "dev": true,
+ "dependencies": {
+ "xss": "^1.0.6"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz",
+ "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.12.0",
+ "invariant": "^2.2.4",
+ "semver": "^5.5.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.0.tgz",
+ "integrity": "sha512-mkLq8nwaXmDtFmRkQ8ED/eA2CnVw4zr7dCztKalZXBvdK5EeNUAesrrwUqjQEzFgomJssayzB0aqlOsP1vGLqg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.0",
+ "@babel/helper-module-transforms": "^7.11.0",
+ "@babel/helpers": "^7.10.4",
+ "@babel/parser": "^7.11.0",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.11.0",
+ "@babel/types": "^7.11.0",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.2",
+ "lodash": "^4.17.19",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@babel/core/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@babel/core/node_modules/resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "dependencies": {
+ "path-parse": "^1.0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/@babel/core/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz",
+ "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.11.0",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "node_modules/@babel/generator/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
+ "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz",
+ "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-explode-assignable-expression": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz",
+ "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.10.4",
+ "browserslist": "^4.12.0",
+ "invariant": "^2.2.4",
+ "levenary": "^1.1.1",
+ "semver": "^5.5.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz",
+ "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-member-expression-to-functions": "^7.10.5",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz",
+ "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-regex": "^7.10.4",
+ "regexpu-core": "^4.7.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-define-map": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz",
+ "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/types": "^7.10.5",
+ "lodash": "^4.17.19"
+ }
+ },
+ "node_modules/@babel/helper-explode-assignable-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz",
+ "integrity": "sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz",
+ "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
+ "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.11.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "node_modules/@babel/helper-regex": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz",
+ "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.19"
+ }
+ },
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz",
+ "integrity": "sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-wrap-function": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
+ "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz",
+ "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz",
+ "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz",
+ "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.0.tgz",
+ "integrity": "sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw==",
+ "dev": true,
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz",
+ "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-remap-async-to-generator": "^7.10.4",
+ "@babel/plugin-syntax-async-generators": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-properties": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz",
+ "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-decorators": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.5.tgz",
+ "integrity": "sha512-Sc5TAQSZuLzgY0664mMDn24Vw2P8g/VhyLyGPaWiHahhgLqeZvcGeyBZOrJW0oSKIK2mvQ22a1ENXBIQLhrEiQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.10.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-decorators": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-dynamic-import": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz",
+ "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz",
+ "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-json-strings": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz",
+ "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz",
+ "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
+ "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz",
+ "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-transform-parameters": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz",
+ "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-chaining": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz",
+ "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-methods": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz",
+ "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz",
+ "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz",
+ "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-decorators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.4.tgz",
+ "integrity": "sha512-2NaoC6fAk2VMdhY1eerkfHV+lVYC1u8b+jmRJISqANCJlTxYy19HGdIkkQtix2UtkcPuPu+IlDgrVseZnU03bw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-flow": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.10.4.tgz",
+ "integrity": "sha512-yxQsX1dJixF4qEEdzVbst3SZQ58Nrooz8NV9Z9GL4byTE25BvJgl5lf0RECUf0fh28rZBb/RYTWn/eeKwCMrZQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz",
+ "integrity": "sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz",
+ "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.4.tgz",
+ "integrity": "sha512-oSAEz1YkBCAKr5Yiq8/BNtvSAPwkp/IyUnwZogd8p+F0RuYQQrLeRUzIQhueQTTBy/F+a40uS7OFKxnkRvmvFQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz",
+ "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz",
+ "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-remap-async-to-generator": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz",
+ "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz",
+ "integrity": "sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz",
+ "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-define-map": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
+ "globals": "^11.1.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz",
+ "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz",
+ "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz",
+ "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz",
+ "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz",
+ "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-flow-strip-types": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.10.4.tgz",
+ "integrity": "sha512-XTadyuqNst88UWBTdLjM+wEY7BFnY2sYtPyAidfC7M/QaZnSuIZpMvLxqGT7phAcnGyWh/XQFLKcGf04CnvxSQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-flow": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz",
+ "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz",
+ "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-literals": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz",
+ "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz",
+ "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz",
+ "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.10.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz",
+ "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz",
+ "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-hoist-variables": "^7.10.4",
+ "@babel/helper-module-transforms": "^7.10.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-umd": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz",
+ "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz",
+ "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-new-target": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz",
+ "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz",
+ "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz",
+ "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz",
+ "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz",
+ "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-transform": "^0.14.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz",
+ "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz",
+ "integrity": "sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "resolve": "^1.8.1",
+ "semver": "^5.5.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime/node_modules/resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "dependencies": {
+ "path-parse": "^1.0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz",
+ "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz",
+ "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz",
+ "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-regex": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz",
+ "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz",
+ "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz",
+ "integrity": "sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.10.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-typescript": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz",
+ "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz",
+ "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-env": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz",
+ "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.11.0",
+ "@babel/helper-compilation-targets": "^7.10.4",
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-proposal-async-generator-functions": "^7.10.4",
+ "@babel/plugin-proposal-class-properties": "^7.10.4",
+ "@babel/plugin-proposal-dynamic-import": "^7.10.4",
+ "@babel/plugin-proposal-export-namespace-from": "^7.10.4",
+ "@babel/plugin-proposal-json-strings": "^7.10.4",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
+ "@babel/plugin-proposal-numeric-separator": "^7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "^7.11.0",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.10.4",
+ "@babel/plugin-proposal-optional-chaining": "^7.11.0",
+ "@babel/plugin-proposal-private-methods": "^7.10.4",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.10.4",
+ "@babel/plugin-syntax-async-generators": "^7.8.0",
+ "@babel/plugin-syntax-class-properties": "^7.10.4",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.0",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.0",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.0",
+ "@babel/plugin-syntax-top-level-await": "^7.10.4",
+ "@babel/plugin-transform-arrow-functions": "^7.10.4",
+ "@babel/plugin-transform-async-to-generator": "^7.10.4",
+ "@babel/plugin-transform-block-scoped-functions": "^7.10.4",
+ "@babel/plugin-transform-block-scoping": "^7.10.4",
+ "@babel/plugin-transform-classes": "^7.10.4",
+ "@babel/plugin-transform-computed-properties": "^7.10.4",
+ "@babel/plugin-transform-destructuring": "^7.10.4",
+ "@babel/plugin-transform-dotall-regex": "^7.10.4",
+ "@babel/plugin-transform-duplicate-keys": "^7.10.4",
+ "@babel/plugin-transform-exponentiation-operator": "^7.10.4",
+ "@babel/plugin-transform-for-of": "^7.10.4",
+ "@babel/plugin-transform-function-name": "^7.10.4",
+ "@babel/plugin-transform-literals": "^7.10.4",
+ "@babel/plugin-transform-member-expression-literals": "^7.10.4",
+ "@babel/plugin-transform-modules-amd": "^7.10.4",
+ "@babel/plugin-transform-modules-commonjs": "^7.10.4",
+ "@babel/plugin-transform-modules-systemjs": "^7.10.4",
+ "@babel/plugin-transform-modules-umd": "^7.10.4",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4",
+ "@babel/plugin-transform-new-target": "^7.10.4",
+ "@babel/plugin-transform-object-super": "^7.10.4",
+ "@babel/plugin-transform-parameters": "^7.10.4",
+ "@babel/plugin-transform-property-literals": "^7.10.4",
+ "@babel/plugin-transform-regenerator": "^7.10.4",
+ "@babel/plugin-transform-reserved-words": "^7.10.4",
+ "@babel/plugin-transform-shorthand-properties": "^7.10.4",
+ "@babel/plugin-transform-spread": "^7.11.0",
+ "@babel/plugin-transform-sticky-regex": "^7.10.4",
+ "@babel/plugin-transform-template-literals": "^7.10.4",
+ "@babel/plugin-transform-typeof-symbol": "^7.10.4",
+ "@babel/plugin-transform-unicode-escapes": "^7.10.4",
+ "@babel/plugin-transform-unicode-regex": "^7.10.4",
+ "@babel/preset-modules": "^0.1.3",
+ "@babel/types": "^7.11.0",
+ "browserslist": "^4.12.0",
+ "core-js-compat": "^3.6.2",
+ "invariant": "^2.2.2",
+ "levenary": "^1.1.1",
+ "semver": "^5.5.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-flow": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.10.4.tgz",
+ "integrity": "sha512-XI6l1CptQCOBv+ZKYwynyswhtOKwpZZp5n0LG1QKCo8erRhqjoQV6nvx61Eg30JHpysWQSBwA2AWRU3pBbSY5g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-transform-flow-strip-types": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-modules": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz",
+ "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz",
+ "integrity": "sha512-SdYnvGPv+bLlwkF2VkJnaX/ni1sMNetcGI1+nThF1gyv6Ph8Qucc4ZZAjM5yZcE/AKRXIOTZz7eSRDWOEjPyRQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-transform-typescript": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/register": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.10.5.tgz",
+ "integrity": "sha512-eYHdLv43nyvmPn9bfNfrcC4+iYNwdQ8Pxk1MFJuU/U5LpSYl/PH4dFMazCYZDFVi8ueG3shvO+AQfLrxpYulQw==",
+ "dev": true,
+ "dependencies": {
+ "find-cache-dir": "^2.0.0",
+ "lodash": "^4.17.19",
+ "make-dir": "^2.1.0",
+ "pirates": "^4.0.0",
+ "source-map-support": "^0.5.16"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/register/node_modules/source-map-support": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+ "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.0.tgz",
+ "integrity": "sha512-qArkXsjJq7H+T86WrIFV0Fnu/tNOkZ4cgXmjkzAu3b/58D5mFIO8JH/y77t7C9q0OdDRdh9s7Ue5GasYssxtXw==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "node_modules/@babel/runtime/node_modules/regenerator-runtime": {
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
+ "dev": true
+ },
+ "node_modules/@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz",
+ "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.0",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.0",
+ "@babel/types": "^7.11.0",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@babel/types": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
+ "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "node_modules/@endemolshinegroup/cosmiconfig-typescript-loader": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.2.tgz",
+ "integrity": "sha512-ZHkXKq2XFFmAUdmSZrmqUSIrRM4O9gtkdpxMmV+LQl7kScUnbo6pMnXu6+FTDgZ12aW6SDoZoOJfS56WD+Eu6A==",
+ "dev": true,
+ "dependencies": {
+ "lodash.get": "^4",
+ "make-error": "^1",
+ "ts-node": "^8",
+ "tslib": "^1"
+ },
+ "engines": {
+ "node": ">=8.0.0",
+ "yarn": ">=1.3.0"
+ },
+ "peerDependencies": {
+ "cosmiconfig": ">=5 < 6"
+ }
+ },
+ "node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "0.2.34",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.34.tgz",
+ "integrity": "sha512-XcIn3iYbTEzGIxD0/dY5+4f019jIcEIWBiHc3KrmK/ROahwxmZ/s+tdj97p/5K0klz4zZUiMfUlYP0ajhSJjmA==",
+ "hasInstallScript": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/fontawesome-svg-core": {
+ "version": "1.2.34",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.34.tgz",
+ "integrity": "sha512-0KNN0nc5eIzaJxlv43QcDmTkDY1CqeN6J7OCGSs+fwGPdtv0yOQqRjieopBCmw+yd7uD3N2HeNL3Zm5isDleLg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "^0.2.34"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-brands-svg-icons": {
+ "version": "5.15.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.2.tgz",
+ "integrity": "sha512-YPlVjE1cEO+OJ9I9ay3TQ3I88+XkxMTYwnnddqAboxLhPNGncsHV0DjWOVLCyuAY66yPfyndWwVn4v7vuqsO1g==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "^0.2.34"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-solid-svg-icons": {
+ "version": "5.15.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.2.tgz",
+ "integrity": "sha512-ZfCU+QjaFsdNZmOGmfqEWhzI3JOe37x5dF4kz9GeXvKn/sTxhqMtZ7mh3lBf76SvcYY5/GKFuyG7p1r4iWMQqw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "^0.2.34"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/vue-fontawesome": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-2.0.2.tgz",
+ "integrity": "sha512-ecpKSBUWXsxRJVi/dbOds4tkKwEcBQ1JSDZFzE2jTFpF8xIh3OgTX8POIor6bOltjibr3cdEyvnDjecMwUmxhQ==",
+ "peerDependencies": {
+ "@fortawesome/fontawesome-svg-core": ">= 1.2.0 < 1.3",
+ "vue": "~2"
+ }
+ },
+ "node_modules/@hapi/address": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
+ "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==",
+ "deprecated": "Moved to 'npm install @sideway/address'",
+ "dev": true
+ },
+ "node_modules/@hapi/bourne": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz",
+ "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==",
+ "deprecated": "This version has been deprecated and is no longer supported or maintained",
+ "dev": true
+ },
+ "node_modules/@hapi/hoek": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz",
+ "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==",
+ "deprecated": "This version has been deprecated and is no longer supported or maintained",
+ "dev": true
+ },
+ "node_modules/@hapi/joi": {
+ "version": "15.1.1",
+ "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz",
+ "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==",
+ "deprecated": "Switch to 'npm install joi'",
+ "dev": true,
+ "dependencies": {
+ "@hapi/address": "2.x.x",
+ "@hapi/bourne": "1.x.x",
+ "@hapi/hoek": "8.x.x",
+ "@hapi/topo": "3.x.x"
+ }
+ },
+ "node_modules/@hapi/topo": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz",
+ "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==",
+ "deprecated": "This version has been deprecated and is no longer supported or maintained",
+ "dev": true,
+ "dependencies": {
+ "@hapi/hoek": "^8.3.0"
+ }
+ },
+ "node_modules/@intervolga/optimize-cssnano-plugin": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz",
+ "integrity": "sha512-zN69TnSr0viRSU6cEDIcuPcP67QcpQ6uHACg58FiN9PDrU6SLyGW3MR4tiISbYxy1kDWAVPwD+XwQTWE5cigAA==",
+ "dev": true,
+ "dependencies": {
+ "cssnano": "^4.0.0",
+ "cssnano-preset-default": "^4.0.0",
+ "postcss": "^7.0.0"
+ },
+ "peerDependencies": {
+ "webpack": "^4.0.0"
+ }
+ },
+ "node_modules/@intervolga/optimize-cssnano-plugin/node_modules/postcss": {
+ "version": "7.0.32",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz",
+ "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ }
+ },
+ "node_modules/@intervolga/optimize-cssnano-plugin/node_modules/supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz",
+ "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz",
+ "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/source-map": "^24.9.0",
+ "chalk": "^2.0.1",
+ "slash": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/console/node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz",
+ "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^24.7.1",
+ "@jest/reporters": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "ansi-escapes": "^3.0.0",
+ "chalk": "^2.0.1",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.1.15",
+ "jest-changed-files": "^24.9.0",
+ "jest-config": "^24.9.0",
+ "jest-haste-map": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-regex-util": "^24.3.0",
+ "jest-resolve": "^24.9.0",
+ "jest-resolve-dependencies": "^24.9.0",
+ "jest-runner": "^24.9.0",
+ "jest-runtime": "^24.9.0",
+ "jest-snapshot": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-validate": "^24.9.0",
+ "jest-watcher": "^24.9.0",
+ "micromatch": "^3.1.10",
+ "p-each-series": "^1.0.0",
+ "realpath-native": "^1.1.0",
+ "rimraf": "^2.5.4",
+ "slash": "^2.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/core/node_modules/ansi-escapes": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@jest/core/node_modules/ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@jest/core/node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/@jest/core/node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@jest/core/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz",
+ "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/fake-timers": "^24.9.0",
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "jest-mock": "^24.9.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz",
+ "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-mock": "^24.9.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz",
+ "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "chalk": "^2.0.1",
+ "exit": "^0.1.2",
+ "glob": "^7.1.2",
+ "istanbul-lib-coverage": "^2.0.2",
+ "istanbul-lib-instrument": "^3.0.1",
+ "istanbul-lib-report": "^2.0.4",
+ "istanbul-lib-source-maps": "^3.0.1",
+ "istanbul-reports": "^2.2.6",
+ "jest-haste-map": "^24.9.0",
+ "jest-resolve": "^24.9.0",
+ "jest-runtime": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-worker": "^24.6.0",
+ "node-notifier": "^5.4.2",
+ "slash": "^2.0.0",
+ "source-map": "^0.6.0",
+ "string-length": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/reporters/node_modules/node-notifier": {
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz",
+ "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==",
+ "dev": true,
+ "dependencies": {
+ "growly": "^1.3.0",
+ "is-wsl": "^1.1.0",
+ "semver": "^5.5.0",
+ "shellwords": "^0.1.1",
+ "which": "^1.3.0"
+ }
+ },
+ "node_modules/@jest/reporters/node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@jest/reporters/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz",
+ "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.1.15",
+ "source-map": "^0.6.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/source-map/node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz",
+ "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "@types/istanbul-lib-coverage": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz",
+ "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^24.9.0",
+ "jest-haste-map": "^24.9.0",
+ "jest-runner": "^24.9.0",
+ "jest-runtime": "^24.9.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz",
+ "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.1.0",
+ "@jest/types": "^24.9.0",
+ "babel-plugin-istanbul": "^5.1.0",
+ "chalk": "^2.0.1",
+ "convert-source-map": "^1.4.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "graceful-fs": "^4.1.15",
+ "jest-haste-map": "^24.9.0",
+ "jest-regex-util": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "micromatch": "^3.1.10",
+ "pirates": "^4.0.1",
+ "realpath-native": "^1.1.0",
+ "slash": "^2.0.0",
+ "source-map": "^0.6.1",
+ "write-file-atomic": "2.4.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@jest/transform/node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@jest/transform/node_modules/write-file-atomic": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz",
+ "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz",
+ "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^1.1.1",
+ "@types/yargs": "^13.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@mrmlnc/readdir-enhanced": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
+ "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
+ "dev": true,
+ "dependencies": {
+ "call-me-maybe": "^1.0.1",
+ "glob-to-regexp": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
+ "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.3",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir/node_modules/@nodelib/fs.stat": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
+ "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
+ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz",
+ "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.3",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/ci-detect": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.3.0.tgz",
+ "integrity": "sha512-oN3y7FAROHhrAt7Rr7PnTSwrHrZVRTS2ZbyxeQwSSYD0ifwM3YNgQqbaRmjcWoPyq77MjchusjJDspbzMmip1Q=="
+ },
+ "node_modules/@npmcli/git": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.0.3.tgz",
+ "integrity": "sha512-c/ODsV5ppjB12VDXKc6hzVNgg6ZJX/etILUn3WgF5NLAYBhQLJ3fBq6uB2jQD4OwqOzJdPT1/xA3Xh3aaWGk5w==",
+ "dependencies": {
+ "@npmcli/promise-spawn": "^1.1.0",
+ "lru-cache": "^6.0.0",
+ "mkdirp": "^1.0.3",
+ "npm-pick-manifest": "^6.0.0",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^1.1.1",
+ "semver": "^7.3.2",
+ "unique-filename": "^1.1.1",
+ "which": "^2.0.2"
+ }
+ },
+ "node_modules/@npmcli/git/node_modules/semver": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/installed-package-contents": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.5.tgz",
+ "integrity": "sha512-aKIwguaaqb6ViwSOFytniGvLPb9SMCUm39TgM3SfUo7n0TxUMbwoXfpwyvQ4blm10lzbAwTsvjr7QZ85LvTi4A==",
+ "dependencies": {
+ "npm-bundled": "^1.1.1",
+ "npm-normalize-package-bin": "^1.0.1",
+ "read-package-json-fast": "^1.1.1",
+ "readdir-scoped-modules": "^1.1.0"
+ },
+ "bin": {
+ "installed-package-contents": "index.js"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@npmcli/move-file": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz",
+ "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==",
+ "dependencies": {
+ "mkdirp": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/promise-spawn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.2.0.tgz",
+ "integrity": "sha512-nFtqjVETliApiRdjbYwKwhlSHx2ZMagyj5b9YbNt0BWeeOVxJd47ZVE2u16vxDHyTOZvk+YLV7INwfAE9a2uow==",
+ "dependencies": {
+ "infer-owner": "^1.0.4"
+ }
+ },
+ "node_modules/@npmcli/run-script": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.4.0.tgz",
+ "integrity": "sha512-evlD0Ur2ILGyTP7FfMYi90x80bto9+nEbGjoWzdF+gmIX3HuA1nW0Ghj91JFaTJAHiXnDEEduZS24oAve/aeOA==",
+ "dependencies": {
+ "@npmcli/promise-spawn": "^1.2.0",
+ "infer-owner": "^1.0.4",
+ "node-gyp": "^6.1.0",
+ "read-package-json-fast": "^1.1.3"
+ }
+ },
+ "node_modules/@oclif/color": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@oclif/color/-/color-0.1.2.tgz",
+ "integrity": "sha512-M9o+DOrb8l603qvgz1FogJBUGLqcMFL1aFg2ZEL0FbXJofiNTLOWIeB4faeZTLwE6dt0xH9GpCVpzksMMzGbmA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^3.0.0",
+ "strip-ansi": "^5.2.0",
+ "supports-color": "^5.4.0",
+ "tslib": "^1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/color/node_modules/ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/color/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/color/node_modules/chalk/node_modules/ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "dependencies": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@oclif/color/node_modules/chalk/node_modules/supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/color/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@oclif/color/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@oclif/color/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/color/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/command": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.7.0.tgz",
+ "integrity": "sha512-TkknFtWcZI8te0E8sW+ohiblExrLx73rIcV4KdIzDX01u+oTZWZaap51F6TSGFnR/Gey0WctaDvJhZlt4xgKdA==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/config": "^1.15.1",
+ "@oclif/errors": "^1.3.3",
+ "@oclif/parser": "^3.8.3",
+ "@oclif/plugin-help": "^3",
+ "debug": "^4.1.1",
+ "semver": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ },
+ "peerDependencies": {
+ "@oclif/config": "^1"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/@oclif/plugin-help": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.1.0.tgz",
+ "integrity": "sha512-orSWpXGlJaX16eSjAtI8scA8QhrjQOaCSHodEx52t18JKbIVzG8jcngugyWAOB/V4jhPl0rdiVk9XFsaIIiG2g==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/command": "^1.5.20",
+ "@oclif/config": "^1.15.1",
+ "chalk": "^2.4.1",
+ "indent-string": "^4.0.0",
+ "lodash.template": "^4.4.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0",
+ "widest-line": "^2.0.1",
+ "wrap-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@oclif/command/node_modules/string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/widest-line": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+ "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/widest-line/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/widest-line/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/widest-line/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/wrap-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz",
+ "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/command/node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/config": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.16.0.tgz",
+ "integrity": "sha512-vOnMPQcHokC03WBCuLipTxksTwgZcmDOnH2H0UHqndfKKN9GVDzpZTH6zaFVQBdjTME5VtRzg9A2UaNmq6OXWw==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/errors": "^1.3.3",
+ "@oclif/parser": "^3.8.0",
+ "debug": "^4.1.1",
+ "globby": "^11.0.1",
+ "is-wsl": "^2.1.1",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/@nodelib/fs.stat": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
+ "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/fast-glob": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz",
+ "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.0",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.2",
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/glob-parent": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+ "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/globby": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
+ "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.1.1",
+ "ignore": "^5.1.4",
+ "merge2": "^1.3.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/micromatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+ "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@oclif/config/node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/config/node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/@oclif/errors": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.3.tgz",
+ "integrity": "sha512-EJR6AIOEkt/NnARNIVAskPDVtdhtO5TTNXmhDrGqMoWVsr0R6DkkLrMyq95BmHvlVWM1nduoq4fQPuCyuF2jaA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^3.0.0",
+ "fs-extra": "^9.0.1",
+ "indent-string": "^4.0.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/errors/node_modules/ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/errors/node_modules/clean-stack": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.0.tgz",
+ "integrity": "sha512-RHxtgFvXsRQ+1AM7dlozLDY7ssmvUUh0XEnfnyhYgJTO6beNZHBogiaCwGM9Q3rFrUkYxOtsZRC0zAturg5bjg==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@oclif/errors/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@oclif/errors/node_modules/fs-extra": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
+ "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
+ "dev": true,
+ "dependencies": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@oclif/errors/node_modules/jsonfile": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
+ "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^1.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/@oclif/errors/node_modules/strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/errors/node_modules/universalify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+ "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/@oclif/linewrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz",
+ "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==",
+ "dev": true
+ },
+ "node_modules/@oclif/parser": {
+ "version": "3.8.5",
+ "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.5.tgz",
+ "integrity": "sha512-yojzeEfmSxjjkAvMRj0KzspXlMjCfBzNRPkWw8ZwOSoNWoJn+OCS/m/S+yfV6BvAM4u2lTzX9Y5rCbrFIgkJLg==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/errors": "^1.2.2",
+ "@oclif/linewrap": "^1.0.0",
+ "chalk": "^2.4.2",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/plugin-autocomplete": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-autocomplete/-/plugin-autocomplete-0.2.0.tgz",
+ "integrity": "sha512-pHbaE2PH7d9lHjCgFrrQ+ZIwvY+7OAQaGoaANqDbicBNDK/Rszt4N4oGj22dJT7sCQ8a/3Eh942rjxYIq9Mi9Q==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/command": "^1.5.13",
+ "@oclif/config": "^1.13.0",
+ "chalk": "^2.4.1",
+ "cli-ux": "^5.2.1",
+ "debug": "^4.0.0",
+ "fs-extra": "^7.0.0",
+ "moment": "^2.22.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/plugin-autocomplete/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@oclif/plugin-autocomplete/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@oclif/plugin-help": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-2.2.3.tgz",
+ "integrity": "sha512-bGHUdo5e7DjPJ0vTeRBMIrfqTRDBfyR5w0MP41u0n3r7YG5p14lvMmiCXxi6WDaP2Hw5nqx3PnkAIntCKZZN7g==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/command": "^1.5.13",
+ "chalk": "^2.4.1",
+ "indent-string": "^4.0.0",
+ "lodash.template": "^4.4.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0",
+ "widest-line": "^2.0.1",
+ "wrap-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/widest-line": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+ "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/wrap-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz",
+ "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-not-found": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-1.2.4.tgz",
+ "integrity": "sha512-G440PCuMi/OT8b71aWkR+kCWikngGtyRjOR24sPMDbpUFV4+B3r51fz1fcqeUiiEOYqUpr0Uy/sneUe1O/NfBg==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/color": "^0.x",
+ "@oclif/command": "^1.6.0",
+ "cli-ux": "^4.9.0",
+ "fast-levenshtein": "^2.0.6",
+ "lodash": "^4.17.13"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/plugin-not-found/node_modules/ansi-escapes": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-not-found/node_modules/ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/plugin-not-found/node_modules/cli-ux": {
+ "version": "4.9.3",
+ "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-4.9.3.tgz",
+ "integrity": "sha512-/1owvF0SZ5Gn54cgrikJ0QskgTzeg30HGjkmjFoaHDJzAqFpuX1DBpFR8aLvsE1J5s9MgeYRENQK4BFwOag5VA==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/errors": "^1.2.2",
+ "@oclif/linewrap": "^1.0.0",
+ "@oclif/screen": "^1.0.3",
+ "ansi-escapes": "^3.1.0",
+ "ansi-styles": "^3.2.1",
+ "cardinal": "^2.1.1",
+ "chalk": "^2.4.1",
+ "clean-stack": "^2.0.0",
+ "extract-stack": "^1.0.0",
+ "fs-extra": "^7.0.0",
+ "hyperlinker": "^1.0.0",
+ "indent-string": "^3.2.0",
+ "is-wsl": "^1.1.0",
+ "lodash": "^4.17.11",
+ "password-prompt": "^1.0.7",
+ "semver": "^5.6.0",
+ "strip-ansi": "^5.0.0",
+ "supports-color": "^5.5.0",
+ "supports-hyperlinks": "^1.0.1",
+ "treeify": "^1.1.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/plugin-not-found/node_modules/extract-stack": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-1.0.0.tgz",
+ "integrity": "sha1-uXrK+UQe6iMyUpYktzL8WhyBZfo=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-not-found/node_modules/indent-string": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+ "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@oclif/plugin-not-found/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@oclif/plugin-plugins": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-1.9.0.tgz",
+ "integrity": "sha512-sq31nJk/n5pH5qGDioj2Z9x6MlRUrc/kkQrfCYKRPbQM80qewSP4RcPK3/gDvDSOAWD3wLAK9oMbDQO9lqImMA==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/color": "^0.x",
+ "@oclif/command": "^1.5.12",
+ "chalk": "^2.4.2",
+ "cli-ux": "^5.2.1",
+ "debug": "^4.1.0",
+ "fs-extra": "^7.0.1",
+ "http-call": "^5.2.2",
+ "load-json-file": "^5.2.0",
+ "npm-run-path": "^3.0.0",
+ "semver": "^7.3.2",
+ "tslib": "^2.0.0",
+ "yarn": "^1.21.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/plugin-plugins/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@oclif/plugin-plugins/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@oclif/plugin-plugins/node_modules/npm-run-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz",
+ "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/plugin-plugins/node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oclif/plugin-plugins/node_modules/semver": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@oclif/plugin-plugins/node_modules/tslib": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.0.tgz",
+ "integrity": "sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g==",
+ "dev": true
+ },
+ "node_modules/@oclif/plugin-warn-if-update-available": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-1.7.0.tgz",
+ "integrity": "sha512-Nwyz3BJ8RhsfQ+OmFSsJSPIfn5YJqMrCzPh72Zgo2jqIjKIBWD8N9vTTe4kZlpeUUn77SyXFfwlBQbNCL5OEuQ==",
+ "dev": true,
+ "dependencies": {
+ "@oclif/command": "^1.5.10",
+ "@oclif/config": "^1.12.8",
+ "@oclif/errors": "^1.2.2",
+ "chalk": "^2.4.1",
+ "debug": "^4.1.0",
+ "fs-extra": "^7.0.0",
+ "http-call": "^5.2.2",
+ "lodash.template": "^4.4.0",
+ "semver": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@oclif/plugin-warn-if-update-available/node_modules/debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@oclif/plugin-warn-if-update-available/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/@oclif/screen": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-1.0.4.tgz",
+ "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=",
+ "dev": true
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "dev": true
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
+ "dev": true
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=",
+ "dev": true
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
+ "dev": true,
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=",
+ "dev": true
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=",
+ "dev": true
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=",
+ "dev": true
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=",
+ "dev": true
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=",
+ "dev": true
+ },
+ "node_modules/@samverschueren/stream-to-observable": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz",
+ "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==",
+ "dev": true,
+ "dependencies": {
+ "any-observable": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@simonwep/pickr": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@simonwep/pickr/-/pickr-1.7.4.tgz",
+ "integrity": "sha512-fq7jgKJT21uWGC1mARBHvvd1JYlEf93o7SuVOB4Lr0x/2UPuNC9Oe9n/GzVeg4oVtqMDfh1wIEJpsdOJEZb+3g==",
+ "dependencies": {
+ "core-js": "^3.6.5",
+ "nanopop": "^2.1.0"
+ }
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@soda/friendly-errors-webpack-plugin": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz",
+ "integrity": "sha512-cWKrGaFX+rfbMrAxVv56DzhPNqOJPZuNIS2HGMELtgGzb+vsMzyig9mml5gZ/hr2BGtSLV+dP2LUEuAL8aG2mQ==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^1.1.3",
+ "error-stack-parser": "^2.0.0",
+ "string-width": "^2.0.0"
+ },
+ "peerDependencies": {
+ "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0"
+ }
+ },
+ "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/string-width/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@soda/get-current-script": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@soda/get-current-script/-/get-current-script-1.0.2.tgz",
+ "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==",
+ "dev": true
+ },
+ "node_modules/@szmarczak/http-timer": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+ "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+ "dependencies": {
+ "defer-to-connect": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@types/accepts": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz",
+ "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/anymatch": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
+ "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
+ "dev": true
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.1.9",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.9.tgz",
+ "integrity": "sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz",
+ "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz",
+ "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.0.13",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.13.tgz",
+ "integrity": "sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.3.0"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.33",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
+ "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==",
+ "dev": true
+ },
+ "node_modules/@types/cookies": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz",
+ "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==",
+ "dev": true,
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/express": "*",
+ "@types/keygrip": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==",
+ "dev": true,
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/d3-format": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-1.3.1.tgz",
+ "integrity": "sha512-KAWvReOKMDreaAwOjdfQMm0HjcUMlQG47GwqdVKgmm20vTd2pucj0a70c3gUSHrnsmo6H2AMrkBsZU2UhJLq8A=="
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.7",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz",
+ "integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "*",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.17.9",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz",
+ "integrity": "sha512-DG0BYg6yO+ePW+XoDENYz8zhNGC3jDDEpComMYn7WJc4mY1Us8Rw9ax2YhJXxpyk2SF47PQAoQ0YyVT1a0bEkA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*"
+ }
+ },
+ "node_modules/@types/fs-capacitor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz",
+ "integrity": "sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz",
+ "integrity": "sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/graphql-upload": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-8.0.3.tgz",
+ "integrity": "sha512-hmLg9pCU/GmxBscg8GCr1vmSoEmbItNNxdD5YH2TJkXm//8atjwuprB+xJBK714JG1dkxbbhp5RHX+Pz1KsCMA==",
+ "dev": true,
+ "dependencies": {
+ "@types/express": "*",
+ "@types/fs-capacitor": "*",
+ "@types/koa": "*",
+ "graphql": "^14.5.3"
+ }
+ },
+ "node_modules/@types/http-assert": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz",
+ "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==",
+ "dev": true
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
+ "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==",
+ "dev": true
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz",
+ "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*",
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "24.9.1",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.9.1.tgz",
+ "integrity": "sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==",
+ "dev": true,
+ "dependencies": {
+ "jest-diff": "^24.3.0"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz",
+ "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==",
+ "dev": true
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
+ "dev": true
+ },
+ "node_modules/@types/keygrip": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
+ "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==",
+ "dev": true
+ },
+ "node_modules/@types/koa": {
+ "version": "2.11.3",
+ "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.3.tgz",
+ "integrity": "sha512-ABxVkrNWa4O/Jp24EYI/hRNqEVRlhB9g09p48neQp4m3xL1TJtdWk2NyNQSMCU45ejeELMQZBYyfstyVvO2H3Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/accepts": "*",
+ "@types/content-disposition": "*",
+ "@types/cookies": "*",
+ "@types/http-assert": "*",
+ "@types/keygrip": "*",
+ "@types/koa-compose": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/koa-compose": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz",
+ "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/koa": "*"
+ }
+ },
+ "node_modules/@types/loader-utils": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@types/loader-utils/-/loader-utils-1.1.3.tgz",
+ "integrity": "sha512-euKGFr2oCB3ASBwG39CYJMR3N9T0nanVqXdiH7Zu/Nqddt6SmFRxytq/i2w9LQYNQekEtGBz+pE3qG6fQTNvRg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/webpack": "*"
+ }
+ },
+ "node_modules/@types/lodash": {
+ "version": "4.14.158",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.158.tgz",
+ "integrity": "sha512-InCEXJNTv/59yO4VSfuvNrZHt7eeNtWQEgnieIA+mIC+MOWM9arOWG2eQ8Vhk6NbOre6/BidiXhkZYeDY9U35w=="
+ },
+ "node_modules/@types/long": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
+ "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==",
+ "dev": true
+ },
+ "node_modules/@types/mime": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
+ "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==",
+ "dev": true
+ },
+ "node_modules/@types/minimatch": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "14.0.27",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz",
+ "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g=="
+ },
+ "node_modules/@types/node-fetch": {
+ "version": "2.5.7",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz",
+ "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^3.0.0"
+ }
+ },
+ "node_modules/@types/node-fetch/node_modules/form-data": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
+ "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
+ "dev": true
+ },
+ "node_modules/@types/q": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
+ "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==",
+ "dev": true
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz",
+ "integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==",
+ "dev": true
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
+ "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
+ "dev": true
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.13.5",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz",
+ "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/express-serve-static-core": "*",
+ "@types/mime": "*"
+ }
+ },
+ "node_modules/@types/source-list-map": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
+ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
+ "dev": true
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
+ "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==",
+ "dev": true
+ },
+ "node_modules/@types/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
+ "dev": true
+ },
+ "node_modules/@types/strip-json-comments": {
+ "version": "0.0.30",
+ "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
+ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
+ "dev": true
+ },
+ "node_modules/@types/tapable": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz",
+ "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==",
+ "dev": true
+ },
+ "node_modules/@types/uglify-js": {
+ "version": "3.9.3",
+ "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.9.3.tgz",
+ "integrity": "sha512-KswB5C7Kwduwjj04Ykz+AjvPcfgv/37Za24O2EDzYNbwyzOo8+ydtvzUfZ5UMguiVu29Gx44l1A6VsPPcmYu9w==",
+ "dev": true,
+ "dependencies": {
+ "source-map": "^0.6.1"
+ }
+ },
+ "node_modules/@types/webpack": {
+ "version": "4.41.21",
+ "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.21.tgz",
+ "integrity": "sha512-2j9WVnNrr/8PLAB5csW44xzQSJwS26aOnICsP3pSGCEdsu6KYtfQ6QJsVUKHWRnm1bL7HziJsfh5fHqth87yKA==",
+ "dev": true,
+ "dependencies": {
+ "@types/anymatch": "*",
+ "@types/node": "*",
+ "@types/tapable": "*",
+ "@types/uglify-js": "*",
+ "@types/webpack-sources": "*",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/@types/webpack-sources": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-1.4.2.tgz",
+ "integrity": "sha512-77T++JyKow4BQB/m9O96n9d/UUHWLQHlcqXb9Vsf4F1+wKNrrlWNFPDLKNT92RJnCSL6CieTc+NDXtCVZswdTw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/source-list-map": "*",
+ "source-map": "^0.7.3"
+ }
+ },
+ "node_modules/@types/webpack-sources/node_modules/source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@types/ws": {
+ "version": "7.2.6",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.2.6.tgz",
+ "integrity": "sha512-Q07IrQUSNpr+cXU4E4LtkSIBPie5GLZyyMC1QtQYRLWz701+XcoVygGUZgvLqElq1nU4ICldMYPnexlBsg3dqQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/yargs": {
+ "version": "13.0.9",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.9.tgz",
+ "integrity": "sha512-xrvhZ4DZewMDhoH1utLtOAwYQy60eYFoXeje30TzM3VOvQlBwQaEpKFq5m34k1wOw2AKIi2pwtiAjdmhvlBUzg==",
+ "dev": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "15.0.0",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
+ "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==",
+ "dev": true
+ },
+ "node_modules/@types/zen-observable": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz",
+ "integrity": "sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg==",
+ "dev": true
+ },
+ "node_modules/@vue/babel-helper-vue-jsx-merge-props": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz",
+ "integrity": "sha512-6tyf5Cqm4m6v7buITuwS+jHzPlIPxbFzEhXR5JGZpbrvOcp1hiQKckd305/3C7C36wFekNTQSxAtgeM0j0yoUw==",
+ "dev": true
+ },
+ "node_modules/@vue/babel-plugin-transform-vue-jsx": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.1.2.tgz",
+ "integrity": "sha512-YfdaoSMvD1nj7+DsrwfTvTnhDXI7bsuh+Y5qWwvQXlD24uLgnsoww3qbiZvWf/EoviZMrvqkqN4CBw0W3BWUTQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.2.0",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
+ "html-tags": "^2.0.0",
+ "lodash.kebabcase": "^4.1.1",
+ "svg-tags": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@vue/babel-preset-app": {
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.4.6.tgz",
+ "integrity": "sha512-urIa6Qk3lKacLvscrzxMNyYlTqKFcPAUo5MohOjv1ISZ9PssHw693WTOrqSC0XksdMLtp/rnLvc6l5G8Muk0lw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.9.6",
+ "@babel/helper-compilation-targets": "^7.9.6",
+ "@babel/helper-module-imports": "^7.8.3",
+ "@babel/plugin-proposal-class-properties": "^7.8.3",
+ "@babel/plugin-proposal-decorators": "^7.8.3",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-jsx": "^7.8.3",
+ "@babel/plugin-transform-runtime": "^7.9.6",
+ "@babel/preset-env": "^7.9.6",
+ "@babel/runtime": "^7.9.6",
+ "@vue/babel-preset-jsx": "^1.1.2",
+ "babel-plugin-dynamic-import-node": "^2.3.3",
+ "core-js": "^3.6.5",
+ "core-js-compat": "^3.6.5",
+ "semver": "^6.1.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "*",
+ "core-js": "^3"
+ },
+ "peerDependenciesMeta": {
+ "core-js": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/babel-preset-app/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@vue/babel-preset-jsx": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.1.2.tgz",
+ "integrity": "sha512-zDpVnFpeC9YXmvGIDSsKNdL7qCG2rA3gjywLYHPCKDT10erjxF4U+6ay9X6TW5fl4GsDlJp9bVfAVQAAVzxxvQ==",
+ "dev": true,
+ "dependencies": {
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.1.2",
+ "@vue/babel-sugar-functional-vue": "^1.1.2",
+ "@vue/babel-sugar-inject-h": "^1.1.2",
+ "@vue/babel-sugar-v-model": "^1.1.2",
+ "@vue/babel-sugar-v-on": "^1.1.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
... 30882 lines suppressed ...