Skip to content

Commit ce1a893

Browse files
cholco202GitHub Enterprise
authored andcommitted
Merge pull request #1 from SDS/vmax_properties
Vmax properties
2 parents 4f06902 + 60a656e commit ce1a893

3 files changed

Lines changed: 240 additions & 6 deletions

File tree

src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ extern crate xml_attributes_derive;
1414
pub mod brocade;
1515
pub mod error;
1616
pub mod hitachi;
17-
pub mod netapp;
1817
pub mod ir;
1918
pub mod isilon;
19+
pub mod netapp;
2020
pub mod scaleio;
2121
pub mod solidfire;
2222
pub mod telegraf;
@@ -27,3 +27,7 @@ pub mod xtremio;
2727
pub trait IntoPoint {
2828
fn into_point(&self, name: Option<&str>) -> Vec<ir::TsPoint>;
2929
}
30+
31+
pub trait ChildPoint {
32+
fn sub_point(&self, p: &mut ir::TsPoint);
33+
}

src/vmax.rs

Lines changed: 198 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ extern crate serde;
44
extern crate serde_json;
55

66
use error::MetricsResult;
7+
use ChildPoint;
78
use IntoPoint;
89

910
use std::fmt::Debug;
@@ -39,16 +40,16 @@ fn get_data<T>(
3940
where
4041
T: DeserializeOwned + Debug + IntoPoint,
4142
{
42-
let j: T = client
43+
let mut j = client
4344
.get(&format!(
4445
"https://{}/univmax/restapi/{}",
4546
config.endpoint, api_endpoint,
4647
))
4748
.basic_auth(config.user.clone(), Some(config.password.clone()))
4849
.send()?
49-
.error_for_status()?
50-
.json()?;
51-
Ok(j.into_point(Some(point_name)))
50+
.error_for_status()?;
51+
let deserialized: T = j.json()?;
52+
Ok(deserialized.into_point(Some(point_name)))
5253
}
5354

5455
/* Changed the GET to POST and added body parameter to pass additional fields to
@@ -962,4 +963,196 @@ fn test_get_per_array_storagegroup_metrics() {
962963
let i: StorageGroupArrayMetrics = serde_json::from_str(&buff).unwrap();
963964
println!("result: {:#?}", i);
964965
}
965-
//END Section for Test Functions
966+
967+
//For Collecting the VMAX Array System Properties Metrics. This includes the RAW array values for capacity
968+
//which is found in the GUI Unisphere --> Array --> System --> Symmetrix Properties
969+
//https://[username]:[password]@[Unisphere Server]:8443/univmax/restapi/90/sloprovisioning/symmetrix/[Array S/N]
970+
#[test]
971+
fn test_get_slo_provisioning_system_properties() {
972+
use std::fs::File;
973+
use std::io::Read;
974+
975+
let mut f = File::open("tests/vmax/slo_provisioning_system_properties.json").unwrap();
976+
let mut buff = String::new();
977+
f.read_to_string(&mut buff).unwrap();
978+
979+
let i: VmaxSystemCapacity = serde_json::from_str(&buff).unwrap();
980+
println!("result: {:#?}", i);
981+
}
982+
// END Section for Test Functions
983+
984+
// This function is for get_data only, the get_list was not needed. Note the '90' for v9 of the EMC Unisphere software
985+
pub fn get_vmax_array_raw(
986+
client: &reqwest::Client,
987+
config: &VmaxConfig,
988+
symmetrixid: &str,
989+
) -> MetricsResult<Vec<TsPoint>> {
990+
let vmax_raw = get_data::<VmaxSystemCapacity>(
991+
client,
992+
config,
993+
&format!("90/sloprovisioning/symmetrix/{}", symmetrixid),
994+
"vmax_array_raw",
995+
)?;
996+
debug!("result: {:#?}", vmax_raw);
997+
Ok(vmax_raw)
998+
}
999+
1000+
// This is split into objects and sub-objects based upon the new Unisphere release v9
1001+
#[derive(Debug, Deserialize)]
1002+
pub struct VmaxSystemCapacity {
1003+
#[serde(rename = "symmetrixId")]
1004+
pub symmetrix_id: String,
1005+
pub device_count: u64,
1006+
pub ucode: String,
1007+
pub model: String,
1008+
pub local: bool,
1009+
pub default_fba_srp: String,
1010+
pub host_visible_device_count: u64,
1011+
pub system_capacity: SystemCapacity,
1012+
pub system_efficiency: SystemEfficiency,
1013+
pub meta_data_usage: MetaDataUsage,
1014+
#[serde(rename = "sloCompliance")]
1015+
pub slo_compliance: SloComplianceSys,
1016+
#[serde(rename = "physicalCapacity")]
1017+
pub physical_capacity: PhysicalCapacity,
1018+
}
1019+
1020+
impl IntoPoint for VmaxSystemCapacity {
1021+
fn into_point(&self, name: Option<&str>) -> Vec<TsPoint> {
1022+
let mut p = TsPoint::new(name.unwrap_or("unknown"));
1023+
p.add_tag("symmetrix_id", TsValue::String(self.symmetrix_id.clone()));
1024+
p.add_field("device_count", TsValue::Long(self.device_count));
1025+
p.add_field("ucode", TsValue::String(self.ucode.clone()));
1026+
p.add_field("model", TsValue::String(self.model.clone()));
1027+
p.add_field("local", TsValue::Boolean(self.local.clone()));
1028+
p.add_tag(
1029+
"default_fba_srp",
1030+
TsValue::String(self.default_fba_srp.clone()),
1031+
);
1032+
p.add_field(
1033+
"host_visible_device_count",
1034+
TsValue::Long(self.host_visible_device_count),
1035+
);
1036+
self.system_capacity.sub_point(&mut p);
1037+
self.system_efficiency.sub_point(&mut p);
1038+
self.meta_data_usage.sub_point(&mut p);
1039+
self.slo_compliance.sub_point(&mut p);
1040+
self.physical_capacity.sub_point(&mut p);
1041+
vec![p]
1042+
}
1043+
}
1044+
1045+
#[allow(non_snake_case)]
1046+
#[derive(Debug, Deserialize)]
1047+
pub struct SystemCapacity {
1048+
pub subscribed_allocated_tb: f64,
1049+
pub subscribed_total_tb: f64,
1050+
pub snapshot_modified_tb: f64,
1051+
pub snapshot_total_tb: f64,
1052+
pub usable_used_tb: f64,
1053+
pub usable_total_tb: f64,
1054+
pub subscribed_usable_capacity_percent: f64,
1055+
}
1056+
1057+
// This implements a new impl for sub_point based upon EMC metrics
1058+
// Use a tags for the those metrics defined as String value and field for the remaining, but not both
1059+
impl ChildPoint for SystemCapacity {
1060+
fn sub_point(&self, p: &mut TsPoint) {
1061+
p.add_field(
1062+
"subscribed_allocated_tb",
1063+
TsValue::Float(self.subscribed_allocated_tb),
1064+
);
1065+
p.add_field(
1066+
"subscribed_total_tb",
1067+
TsValue::Float(self.subscribed_total_tb),
1068+
);
1069+
p.add_field(
1070+
"snapshot_modified_tb",
1071+
TsValue::Float(self.snapshot_modified_tb),
1072+
);
1073+
p.add_field("snapshot_total_tb", TsValue::Float(self.snapshot_total_tb));
1074+
p.add_field("usable_used_tb", TsValue::Float(self.usable_used_tb));
1075+
p.add_field("usable_total_tb", TsValue::Float(self.usable_total_tb));
1076+
p.add_field(
1077+
"subscribed_usable_capacity_percent",
1078+
TsValue::Float(self.subscribed_usable_capacity_percent),
1079+
);
1080+
}
1081+
}
1082+
1083+
#[allow(non_snake_case)]
1084+
#[derive(Debug, Deserialize)]
1085+
pub struct SystemEfficiency {
1086+
pub overall_efficiency_ratio_to_one: f64,
1087+
pub data_reduction_enabled_percent: f64,
1088+
pub virtual_provisioning_savings_ratio_to_one: f64,
1089+
}
1090+
1091+
impl ChildPoint for SystemEfficiency {
1092+
fn sub_point(&self, p: &mut TsPoint) {
1093+
p.add_field(
1094+
"overall_efficiency_ratio_to_one",
1095+
TsValue::Float(self.overall_efficiency_ratio_to_one),
1096+
);
1097+
p.add_field(
1098+
"data_reduction_enabled_percent",
1099+
TsValue::Float(self.data_reduction_enabled_percent),
1100+
);
1101+
p.add_field(
1102+
"virtual_provisioning_savings_ratio_to_one",
1103+
TsValue::Float(self.virtual_provisioning_savings_ratio_to_one),
1104+
);
1105+
}
1106+
}
1107+
1108+
#[allow(non_snake_case)]
1109+
#[derive(Debug, Deserialize)]
1110+
pub struct MetaDataUsage {
1111+
pub system_meta_data_used_percent: f64,
1112+
pub replication_cache_used_percent: u64,
1113+
}
1114+
1115+
impl ChildPoint for MetaDataUsage {
1116+
fn sub_point(&self, p: &mut TsPoint) {
1117+
p.add_field(
1118+
"system_meta_data_used_percent",
1119+
TsValue::Float(self.system_meta_data_used_percent),
1120+
);
1121+
p.add_field(
1122+
"replication_cache_used_percent",
1123+
TsValue::Long(self.replication_cache_used_percent),
1124+
);
1125+
}
1126+
}
1127+
1128+
#[allow(non_snake_case)]
1129+
#[derive(Debug, Deserialize)]
1130+
pub struct SloComplianceSys {
1131+
pub slo_stable: i64,
1132+
pub slo_marginal: i64,
1133+
pub slo_critical: i64,
1134+
pub no_slo: i64,
1135+
}
1136+
1137+
impl ChildPoint for SloComplianceSys {
1138+
fn sub_point(&self, p: &mut TsPoint) {
1139+
p.add_field("slo_stable", TsValue::SignedLong(self.slo_stable));
1140+
p.add_field("slo_marginal", TsValue::SignedLong(self.slo_marginal));
1141+
p.add_field("slo_critical", TsValue::SignedLong(self.slo_critical));
1142+
p.add_field("no_slo", TsValue::SignedLong(self.no_slo));
1143+
}
1144+
}
1145+
1146+
#[allow(non_snake_case)]
1147+
#[derive(Debug, Deserialize)]
1148+
pub struct PhysicalCapacity {
1149+
pub used_capacity_gb: f64,
1150+
pub total_capacity_gb: f64,
1151+
}
1152+
1153+
impl ChildPoint for PhysicalCapacity {
1154+
fn sub_point(&self, p: &mut TsPoint) {
1155+
p.add_field("used_capacity_gb", TsValue::Float(self.used_capacity_gb));
1156+
p.add_field("total_capacity_gb", TsValue::Float(self.total_capacity_gb));
1157+
}
1158+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"symmetrixId": "000196702346",
3+
"device_count": 3470,
4+
"ucode": "5977.1125.1125",
5+
"model": "VMAX200K",
6+
"local": true,
7+
"default_fba_srp": "SRP_1",
8+
"system_capacity": {
9+
"subscribed_allocated_tb": 439.53,
10+
"subscribed_total_tb": 693.84,
11+
"snapshot_modified_tb": 0,
12+
"snapshot_total_tb": 0,
13+
"usable_used_tb": 440.74,
14+
"usable_total_tb": 1070.61,
15+
"subscribed_usable_capacity_percent": 65
16+
},
17+
"system_efficiency": {
18+
"overall_efficiency_ratio_to_one": 1.6,
19+
"data_reduction_enabled_percent": 0,
20+
"virtual_provisioning_savings_ratio_to_one": 1.6
21+
},
22+
"meta_data_usage": {
23+
"system_meta_data_used_percent": 56,
24+
"replication_cache_used_percent": 0
25+
},
26+
"sloCompliance": {
27+
"slo_stable": 4,
28+
"slo_marginal": 0,
29+
"slo_critical": 0,
30+
"no_slo": 78
31+
},
32+
"physicalCapacity": {
33+
"used_capacity_gb": 1325680.37,
34+
"total_capacity_gb": 1325680.37
35+
},
36+
"host_visible_device_count": 2078
37+
}

0 commit comments

Comments
 (0)