blob: 1148ba9d1716ecd0672f7561ea8525379c360785 [file] [log] [blame]
/*
* 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.karaf.decanter.collector.openstack;
import org.apache.karaf.decanter.api.marshaller.Unmarshaller;
import org.apache.karaf.decanter.collector.utils.PropertiesPreparator;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Component(
service = Runnable.class,
name = "org.apache.karaf.decanter.collector.openstack",
immediate = true,
property = {
"decanter.collector.name=openstack",
"scheduler.period:Long=300",
"scheduler.concurrent:Boolean=false",
"scheduler.name=decanter-collector-openstack"
}
)
public class OpenstackCollector implements Runnable {
@Reference
public EventAdmin dispatcher;
@Reference
public Unmarshaller unmarshaller;
private final static Logger LOGGER = LoggerFactory.getLogger(OpenstackCollector.class);
private Dictionary<String, Object> config;
private String topic;
private URL identity;
private String username;
private String password;
private String domain;
private String project;
private boolean computeEnabled = true;
private String compute = null;
private boolean computeUsageFlatten = true;
private boolean blockStorageEnabled = true;
private String blockStorage = null;
private boolean imageEnabled = true;
private String image = null;
private boolean metricEnabled = true;
private String metric = null;
@Activate
public void activate(ComponentContext componentContext) throws Exception {
activate(componentContext.getProperties());
}
public void activate(Dictionary<String, Object> config) throws Exception {
this.config = config;
topic = (config.get(EventConstants.EVENT_TOPIC) != null) ? (String) config.get(EventConstants.EVENT_TOPIC) : "decanter/collect/openstack";
if (config.get("openstack.identity") == null) {
throw new IllegalStateException("openstack.identity is not configured");
}
identity = new URL(config.get("openstack.identity") + "/v3/auth/tokens");
if (config.get("openstack.username") == null) {
throw new IllegalStateException("openstack.username is not configured");
}
username = (String) config.get("openstack.username");
if (config.get("openstack.password") == null) {
throw new IllegalStateException("openstack.password is not configured");
}
password = (String) config.get("openstack.password");
if (config.get("openstack.domain") == null) {
throw new IllegalStateException("openstack.domain is not configured");
}
domain = (String) config.get("openstack.domain");
if (config.get("openstack.project") == null) {
throw new IllegalStateException("openstack.project is not configured");
}
project = (String) config.get("openstack.project");
if (config.get("openstack.compute.enabled") != null) {
computeEnabled = Boolean.parseBoolean((String) config.get("openstack.compute.enabled"));
}
compute = (String) config.get("openstack.compute");
if (config.get("openstack.compute.usage.flatten") != null) {
computeUsageFlatten = Boolean.parseBoolean((String) config.get("openstack.compute.usage.flatten"));
}
if (config.get("openstack.block.storage.enabled") != null) {
blockStorageEnabled = Boolean.parseBoolean((String) config.get("openstack.block.storage.enabled"));
}
blockStorage = (String) config.get("openstack.block.storage");
if (config.get("openstack.image.enabled") != null) {
imageEnabled = Boolean.parseBoolean((String) config.get("openstack.image.enabled"));
}
image = (String) config.get("openstack.image");
if (config.get("openstack.metric.enabled") != null) {
metricEnabled = Boolean.parseBoolean((String) config.get("openstack.metric.enabled"));
}
metric = (String) config.get("openstack.metric");
}
@Override
public void run() {
try {
String token = auth();
if (computeEnabled) {
try {
computeUsage(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute usage", e);
}
try {
computeServers(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute servers", e);
}
try {
computeFlavors(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute flavors", e);
}
try {
computeOsKeypairs(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute OS keypairs", e);
}
try {
computeLimits(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute limits", e);
}
try {
computeOsAggregates(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute OS aggregates", e);
}
try {
computeAvailabilityZones(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute availability zones", e);
}
try {
computeOsHypervisors(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute OS hypervisors", e);
}
try {
computeOsInstanceUsageAuditLog(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute OS instance usage audit log", e);
}
try {
computeOsMigrations(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute OS migrations", e);
}
try {
computeOsServerGroups(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute OS server groups", e);
}
try {
computeOsServices(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get compute OS services", e);
}
}
if (blockStorageEnabled) {
try {
blockStorageVolumeTypes(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage volume types", e);
}
try {
blockStorageVolumesDetail(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage volumes detail", e);
}
try {
blockStorageManageableVolumes(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage manageable volumes", e);
}
try {
blockStorageSnapshotsDetail(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage snapshots detail", e);
}
try {
blockStorageVolumeTransfers(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage volume transfers", e);
}
try {
blockStorageAttachments(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage attachments", e);
}
try {
blockStorageBackups(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage backups", e);
}
try {
blockStorageOsServices(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage OS services", e);
}
try {
blockStorageGroups(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage groups", e);
}
try {
blockStorageGroupSnapshots(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage group snapshots", e);
}
try {
blockStorageGroupTypes(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage group types", e);
}
try {
blockStorageOsHosts(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage OS hosts", e);
}
try {
blockStorageLimits(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage limits", e);
}
try {
blockStorageResourceFilters(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage resource filters", e);
}
try {
blockStorageQosSpecs(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get block storage QoS specs", e);
}
}
if (imageEnabled) {
try {
images(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get images", e);
}
try {
imageStore(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get image store", e);
}
try {
imageTasks(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get image tasks", e);
}
}
if (metricEnabled) {
try {
metric(token, dispatcher);
} catch (Exception e) {
LOGGER.warn("Can't get metric", e);
}
}
} catch (Exception e) {
LOGGER.warn("Can't get openstack details", e);
}
}
protected void computeUsage(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-simple-tenant-usage", token);
if (computeUsageFlatten) {
String extract = response.substring(response.indexOf("[") +1, response.indexOf("]"));
String[] split = extract.split("}, \\{");
for (int i = 0; i < split.length; i++) {
Map<String, Object> data = new HashMap<>();
String use = split[i];
if (!use.startsWith("{")) {
use = "{" + use;
}
if (!use.endsWith("}")) {
use = use + "}";
}
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(use.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
} else {
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
}
protected void computeServers(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/servers/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeFlavors(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/flavors/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeOsKeypairs(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-keypairs", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeLimits(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/limits", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeOsAggregates(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-aggregates", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeAvailabilityZones(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-availability-zone/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeOsHypervisors(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-hypervisors/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeOsInstanceUsageAuditLog(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-instance_usage_audit_log", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeOsMigrations(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-migrations", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeOsServerGroups(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-server-groups", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void computeOsServices(String token, EventAdmin dispatcher) throws Exception {
String response = request(compute + "/os-services", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageVolumeTypes(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/types", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageVolumesDetail(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/volumes/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageManageableVolumes(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/manageable_volumes/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageSnapshotsDetail(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/snapshots/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageVolumeTransfers(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/volume-transfers/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageAttachments(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/attachments/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageBackups(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/backups/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageOsServices(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/os-services", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageGroups(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/groups", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageGroupSnapshots(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/group_snapshots/detail", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageGroupTypes(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/group_types", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageOsHosts(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/os-hosts", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageLimits(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/limits", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageResourceFilters(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/resource_filters", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void blockStorageQosSpecs(String token, EventAdmin dispatcher) throws Exception {
String response = request(blockStorage + "/" + project + "/qos-specs", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void images(String token, EventAdmin dispatcher) throws Exception {
String response = request(image + "/v2/images", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void imageStore(String token, EventAdmin dispatcher) throws Exception {
String response = request(image + "/v2/info/stores", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void imageTasks(String token, EventAdmin dispatcher) throws Exception {
String response = request(image + "/v2/tasks", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
protected void metric(String token, EventAdmin dispatcher) throws Exception {
String response = request(metric + "/v1/metric", token);
Map<String, Object> data = new HashMap<>();
data.putAll(unmarshaller.unmarshal(new ByteArrayInputStream(response.getBytes())));
PropertiesPreparator.prepare(data, config);
dispatcher.postEvent(new Event(topic, data));
}
private String request(String url, String token) throws Exception {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("X-Auth-Token", token);
connection.setDoInput(true);
if (connection.getResponseCode() != 200) {
throw new IllegalStateException("Can't get data from " + url + " (" + connection.getResponseCode() + "): " + connection.getResponseMessage());
}
StringBuilder response = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
response.append(line).append("\n");
}
}
return response.toString();
}
protected String auth() throws Exception {
LOGGER.debug("Authentication on {}", identity);
HttpURLConnection connection = (HttpURLConnection) identity.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoInput(true);
connection.setDoOutput(true);
String authJson = "{ \"auth\": { \"identity\": { \"methods\": [\"password\"], \"password\": { \"user\": { \"name\": \"" + username + "\", \"domain\": { \"name\": \"" + domain + "\" }, \"password\": \"" + password + "\" }}}, \"scope\": { \"project\": { \"id\": \"" + project + "\" }}}}";
LOGGER.debug("Authentication JSON request:");
LOGGER.debug(authJson);
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()))) {
writer.write(authJson);
writer.flush();
}
if (connection.getResponseCode() != 201) {
throw new IllegalStateException("Can't get token (" + connection.getResponseCode() + "): " + connection.getResponseMessage());
}
return connection.getHeaderField("X-Subject-Token");
}
/**
* For testing purpose.
*/
public void setDispatcher(EventAdmin dispatcher) {
this.dispatcher = dispatcher;
}
}