[
https://issues.apache.org/jira/browse/CLOUDSTACK-8677?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14642711#comment-14642711
]
ASF GitHub Bot commented on CLOUDSTACK-8677:
--------------------------------------------
Github user sedukull commented on a diff in the pull request:
https://github.com/apache/cloudstack/pull/625#discussion_r35534192
--- Diff: server/src/org/apache/cloudstack/report/UsageReporter.java ---
@@ -0,0 +1,473 @@
+// 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.report;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.net.URL;
+import java.net.SocketTimeoutException;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.UnknownHostException;
+import java.io.OutputStreamWriter;
+import java.io.IOException;
+
+import javax.inject.Inject;
+import javax.net.ssl.HttpsURLConnection;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
+
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.component.ComponentMethodInterceptable;
+import com.cloud.utils.concurrency.NamedThreadFactory;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.upgrade.dao.VersionDao;
+import com.cloud.upgrade.dao.VersionVO;
+import com.cloud.storage.dao.DiskOfferingDao;
+import com.cloud.storage.DiskOfferingVO;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.common.util.concurrent.AtomicLongMap;
+
+@Component
+public class UsageReporter extends ManagerBase implements
ComponentMethodInterceptable {
+ public static final Logger s_logger =
Logger.getLogger(UsageReporter.class.getName());
+
+ /* !FIX ME! This should point to a Apache Infra host with SSL! */
+ private String reportHost = "https://call-home.cloudstack.org/report";
+
+ private String uniqueID = null;
+
+ private static UsageReporter s_instance = null;
+
+ private ScheduledExecutorService _executor = null;
+
+ @Inject
+ private ConfigurationDao _configDao;
+ @Inject
+ private HostDao _hostDao;
+ @Inject
+ private ClusterDao _clusterDao;
+ @Inject
+ private PrimaryDataStoreDao _storagePoolDao;
+ @Inject
+ private DataCenterDao _dataCenterDao;
+ @Inject
+ private UserVmDao _userVmDao;
+ @Inject
+ private VMInstanceDao _vmInstance;
+ @Inject
+ private VersionDao _versionDao;
+ @Inject
+ private DiskOfferingDao _diskOfferingDao;
+
+ int usageReportInterval = -1;
+
+ public static UsageReporter getInstance() {
+ return s_instance;
+ }
+
+ public static UsageReporter getInstance(Map<String, String> configs) {
+ s_instance.init(configs);
+ return s_instance;
+ }
+
+ public UsageReporter() {
+ s_instance = this;
+ }
+
+ @Override
+ public boolean start() {
+ init(_configDao.getConfiguration());
+ return true;
+ }
+
+ private void init(Map<String, String> configs) {
+ _executor = Executors.newScheduledThreadPool(1, new
NamedThreadFactory("UsageReporter"));
+
+ usageReportInterval =
NumbersUtil.parseInt(configs.get("usage.report.interval"), 7);
+
+ if (usageReportInterval > 0) {
+ _executor.scheduleWithFixedDelay(new UsageCollector(), 7,
usageReportInterval, TimeUnit.DAYS);
+ }
+
+ uniqueID = getUniqueId();
+ }
+
+ private void sendReport(String reportUri, String uniqueID, Map<String,
Object> reportMap) {
+
+ GsonBuilder builder = new GsonBuilder();
+
+ AtomicGsonAdapter adapter = new AtomicGsonAdapter();
+ builder.registerTypeAdapter(AtomicLongMap.class, adapter);
+
+ Gson gson = builder.create();
+ String report = gson.toJson(reportMap);
+
+ int http_timeout = 15000;
+
+ try {
+ s_logger.info("Usage Report will be send to: " + reportUri);
+ s_logger.debug("REPORT: " + report);
+
+ URL url = new URL(reportUri + "/" + uniqueID);
+
+ HttpsURLConnection conn = (HttpsURLConnection)
url.openConnection();
+ conn.setConnectTimeout(http_timeout);
+ conn.setReadTimeout(http_timeout);
+ conn.setRequestMethod("POST");
+ conn.setDoOutput(true);
+ conn.setRequestProperty("Content-Type", "application/json");
+ conn.setRequestProperty("Accept", "application/json");
+
+ OutputStreamWriter osw = new
OutputStreamWriter(conn.getOutputStream());
+ osw.write(report);
+ osw.flush();
+ osw.close();
+
+ int resp_code = conn.getResponseCode();
+
+ if (resp_code == HttpsURLConnection.HTTP_OK){
+ s_logger.info("Usage Report succesfully send to: " +
reportUri);
+ } else {
+ s_logger.warn("Failed to send Usage Report: " +
conn.getResponseMessage());
+ }
+
+ } catch (UnknownHostException e) {
+ s_logger.warn("Failed to look up Usage Report host: " +
e.getMessage());
+ } catch (SocketTimeoutException e) {
+ s_logger.warn("Sending Usage Report to " + reportUri + " timed
out: " + e.getMessage());
+ } catch (MalformedURLException e) {
+ s_logger.warn(reportUri + " is a invalid URL for sending Usage
Report to: "+ e.getMessage());
+ } catch (ProtocolException e) {
+ s_logger.warn("Sending Usage Report failed due to a invalid
protocol: " + e.getMessage());
+ } catch (IOException e) {
+ s_logger.warn("Failed to write Usage Report due to a
IOException: " + e.getMessage());
+ }
+ }
+
+ @DB
+ private String getUniqueId() {
+ String unique = null;
+ Connection conn = null;
+
+ try {
+ conn = TransactionLegacy.getStandaloneConnection();
+
+ PreparedStatement pstmt = conn.prepareStatement("SELECT
version,updated FROM version ORDER BY id ASC LIMIT 1");
--- End diff --
Is this resource as well closed? Do we want to close resources in exception
path as well.
> Call-home functionality for CloudStack
> --------------------------------------
>
> Key: CLOUDSTACK-8677
> URL: https://issues.apache.org/jira/browse/CLOUDSTACK-8677
> Project: CloudStack
> Issue Type: New Feature
> Security Level: Public(Anyone can view this level - this is the
> default.)
> Components: Management Server
> Affects Versions: Future, 4.6.0
> Reporter: Wido den Hollander
> Assignee: Wido den Hollander
> Fix For: 4.6.0
>
>
> A call-home feature for the CloudStack management server would send
> anonimized reports back to the CloudStack project.
> These statistics will contain numbers and details on how CloudStack will be
> used. It will NOT contain:
> * Hostnames
> * IP-Addresses
> * Instance names
> It will report back:
> * Hosts (Number, version, type, hypervisor)
> * Clusters (Hypervisor en Management type)
> * Primary storage (Type and provider)
> * Zones (Network type and providers)
> * Instances (Number and types)
> This gives the CloudStack project a better insight on how CloudStack is being
> used and allows us to develop accordingly.
> It will be OPT-OUT, using the "usage.report.interval" users can disable usage
> reporting. By default it will run every 7 days and send a JSON document to
> https://call-home.cloudstack.org/
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)