use serde::{Deserialize, Deserializer, Serializer};
use std::mem::transmute;
fn gen_system_class_string() -> String {
"System".to_string()
}
fn gen_pool_class_string() -> String {
"Pool".to_string()
}
fn gen_vol_class_string() -> String {
"Volume".to_string()
}
fn gen_ag_class_string() -> String {
"AccessGroup".to_string()
}
fn gen_fs_class_string() -> String {
"FileSystem".to_string()
}
fn gen_fs_snap_class_string() -> String {
"FsSnapshot".to_string()
}
fn gen_exp_class_string() -> String {
"NfsExport".to_string()
}
fn gen_disk_class_string() -> String {
"Disk".to_string()
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct System {
#[serde(default = "gen_system_class_string")]
class: String,
pub id: String,
pub name: String,
pub status: u32,
pub status_info: String,
plugin_data: Option<String>,
pub fw_version: String,
pub read_cache_pct: i8,
#[serde(deserialize_with = "int_to_sys_mod")]
#[serde(serialize_with = "sys_mod_to_int")]
pub mode: SystemMode,
}
impl System {
pub const READ_CACHE_PCT_NO_SUPPORT: i8 = -2;
pub const READ_CACHE_PCT_UNKNOWN: i8 = -1;
pub const STATUS_UNKNOWN: u32 = 1;
pub const STATUS_OK: u32 = 1 << 1;
pub const STATUS_ERROR: u32 = 1 << 2;
pub const STATUS_DEGRADED: u32 = 1 << 3;
pub const STATUS_PREDICTIVE_FAILURE: u32 = 1 << 4;
pub const STATUS_OTHER: u32 = 1 << 5;
}
#[repr(i8)]
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum SystemMode {
Unknown = -2,
NoSupport = -1,
HardwareRaid = 0,
Hba = 1,
}
fn int_to_sys_mod<'de, D: Deserializer<'de>>(
deserializer: D,
) -> ::std::result::Result<SystemMode, D::Error> {
let i: i8 = Deserialize::deserialize(deserializer)?;
match i {
-1..=1 => unsafe { Ok(transmute::<i8, SystemMode>(i)) },
_ => Ok(SystemMode::Unknown),
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn sys_mod_to_int<S: Serializer>(
m: &SystemMode,
serializer: S,
) -> ::std::result::Result<S::Ok, S::Error> {
serializer.serialize_i8(*m as i8)
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Volume {
#[serde(default = "gen_vol_class_string")]
class: String,
pub id: String,
pub name: String,
#[serde(deserialize_with = "int_to_bool")]
#[serde(serialize_with = "bool_to_int")]
#[serde(rename = "admin_state")]
pub enabled: bool,
pub block_size: u64,
pub num_of_blocks: u64,
plugin_data: Option<String>,
pub vpd83: String,
pub system_id: String,
pub pool_id: String,
}
impl Volume {
pub fn size_bytes(&self) -> u64 {
self.block_size * self.num_of_blocks
}
}
pub enum VolumeReplicateType {
Unknown = -1,
Clone = 2,
Copy = 3,
MirrorSync = 4,
MirrorAsync = 5,
}
#[repr(i32)]
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum RaidType {
Unknown = -1,
Raid0 = 0,
Raid1 = 1,
Raid3 = 3,
Raid4 = 4,
Raid5 = 5,
Raid6 = 6,
Raid10 = 10,
Raid15 = 15,
Raid16 = 16,
Raid50 = 50,
Raid60 = 60,
Raid51 = 51,
Raid61 = 61,
Jbod = 20,
Mixed = 21,
Other = 22,
}
impl From<i32> for RaidType {
fn from(i: i32) -> RaidType {
match i {
0..=6 | 10 | 15 | 16 | 50 | 60 | 51 | 61 | 20..=22 => unsafe {
transmute::<i32, RaidType>(i)
},
_ => RaidType::Unknown,
}
}
}
#[derive(Debug, Clone)]
pub enum PoolMember {
Disk(Disk),
Pool(Pool),
}
#[derive(Debug, Clone)]
pub struct PoolMemberInfo {
pub raid_type: RaidType,
pub members: Vec<PoolMember>,
}
#[derive(Debug, Clone)]
pub struct VolumeRaidInfo {
pub raid_type: RaidType,
pub strip_size: u32,
pub disk_count: u32,
pub min_io_size: u32,
pub opt_io_size: u32,
}
fn int_to_bool<'de, D: Deserializer<'de>>(
deserializer: D,
) -> ::std::result::Result<bool, D::Error> {
let i: i32 = Deserialize::deserialize(deserializer)?;
match i {
1 => Ok(true),
_ => Ok(false),
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn bool_to_int<S: Serializer>(b: &bool, serializer: S) -> ::std::result::Result<S::Ok, S::Error> {
if *b {
serializer.serialize_i8(1i8)
} else {
serializer.serialize_i8(0i8)
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Pool {
#[serde(default = "gen_pool_class_string")]
class: String,
pub id: String,
pub name: String,
pub element_type: u64,
pub unsupported_actions: u64,
pub total_space: u64,
pub free_space: u64,
pub status: u64,
pub status_info: Option<String>,
plugin_data: Option<String>,
pub system_id: String,
}
impl Pool {
pub const ELEMENT_TYPE_POOL: u64 = 1 << 1;
pub const ELEMENT_TYPE_VOLUME: u64 = 1 << 2;
pub const ELEMENT_TYPE_FS: u64 = 1 << 3;
pub const ELEMENT_TYPE_DELTA: u64 = 1 << 4;
pub const ELEMENT_TYPE_VOLUME_FULL: u64 = 1 << 5;
pub const ELEMENT_TYPE_VOLUME_THIN: u64 = 1 << 6;
pub const ELEMENT_TYPE_SYS_RESERVED: u64 = 1 << 10;
pub const UNSUPPORTED_VOLUME_GROW: u64 = 1;
pub const UNSUPPORTED_VOLUME_SHRINK: u64 = 1 << 1;
pub const STATUS_UNKNOWN: u64 = 1;
pub const STATUS_OK: u64 = 1 << 1;
pub const STATUS_OTHER: u64 = 1 << 2;
pub const STATUS_DEGRADED: u64 = 1 << 4;
pub const STATUS_ERROR: u64 = 1 << 5;
pub const STATUS_STOPPED: u64 = 1 << 9;
pub const STATUS_STARTING: u64 = 1 << 10;
pub const STATUS_RECONSTRUCTING: u64 = 1 << 12;
pub const STATUS_VERIFYING: u64 = 1 << 13;
pub const STATUS_INITIALIZING: u64 = 1 << 14;
pub const STATUS_GROWING: u64 = 1 << 15;
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Disk {
#[serde(default = "gen_disk_class_string")]
class: String,
pub id: String,
pub name: String,
#[serde(deserialize_with = "int_to_disk_type")]
#[serde(serialize_with = "disk_type_to_int")]
pub disk_type: DiskType,
pub block_size: u64,
pub num_of_blocks: u64,
pub status: u64,
plugin_data: Option<String>,
pub system_id: String,
pub location: Option<String>,
pub rpm: Option<i32>,
#[serde(deserialize_with = "int_to_disk_link_type")]
#[serde(serialize_with = "disk_link_type_to_int")]
pub link_type: Option<DiskLinkType>,
pub vpd83: Option<String>,
}
#[repr(i32)]
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum DiskType {
Unknown = 0,
Other = 1,
Ata = 3,
Sata = 4,
Sas = 5,
Fc = 6,
Sop = 7,
Scsi = 8,
Lun = 9,
NlSas = 51,
Hdd = 52,
Ssd = 53,
Hybrid = 54,
}
fn int_to_disk_type<'de, D: Deserializer<'de>>(
deserializer: D,
) -> ::std::result::Result<DiskType, D::Error> {
let i: i32 = Deserialize::deserialize(deserializer)?;
match i {
0 | 1 | 3..=9 | 51..=54 => unsafe { Ok(transmute::<i32, DiskType>(i)) },
_ => Ok(DiskType::Unknown),
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn disk_type_to_int<S: Serializer>(
t: &DiskType,
serializer: S,
) -> ::std::result::Result<S::Ok, S::Error> {
serializer.serialize_i32(*t as i32)
}
#[repr(i32)]
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum DiskLinkType {
NoSupport = -2,
Unknown = -1,
Fc = 0,
Ssa = 2,
Sbp = 3,
Srp = 4,
Iscsi = 5,
Sas = 6,
Adt = 7,
Ata = 8,
Usb = 9,
Sop = 10,
PciE = 11,
}
fn int_to_disk_link_type<'de, D: Deserializer<'de>>(
deserializer: D,
) -> ::std::result::Result<Option<DiskLinkType>, D::Error> {
let i: i32 = Deserialize::deserialize(deserializer)?;
match i {
-2..=11 => unsafe { Ok(Some(transmute::<i32, DiskLinkType>(i))) },
_ => Ok(Some(DiskLinkType::Unknown)),
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn disk_link_type_to_int<S: Serializer>(
t: &Option<DiskLinkType>,
serializer: S,
) -> ::std::result::Result<S::Ok, S::Error> {
match *t {
Some(i) => serializer.serialize_i32(i as i32),
None => serializer.serialize_i32(DiskLinkType::Unknown as i32),
}
}
impl Disk {
pub const STATUS_UNKNOWN: u64 = 1;
pub const STATUS_OK: u64 = 1 << 1;
pub const STATUS_OTHER: u64 = 1 << 2;
pub const STATUS_PREDICTIVE_FAILURE: u64 = 1 << 3;
pub const STATUS_ERROR: u64 = 1 << 4;
pub const STATUS_REMOVED: u64 = 1 << 5;
pub const STATUS_STARTING: u64 = 1 << 6;
pub const STATUS_STOPPING: u64 = 1 << 7;
pub const STATUS_STOPPED: u64 = 1 << 8;
pub const STATUS_INITIALIZING: u64 = 1 << 9;
pub const STATUS_MAINTENANCE_MODE: u64 = 1 << 10;
pub const STATUS_SPARE_DISK: u64 = 1 << 11;
pub const STATUS_RECONSTRUCT: u64 = 1 << 12;
pub const STATUS_FREE: u64 = 1 << 13;
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FileSystem {
#[serde(default = "gen_fs_class_string")]
class: String,
pub id: String,
pub name: String,
pub total_space: u64,
pub free_space: u64,
plugin_data: Option<String>,
pub system_id: String,
pub pool_id: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FileSystemSnapShot {
#[serde(default = "gen_fs_snap_class_string")]
class: String,
pub id: String,
pub name: String,
pub ts: u64,
plugin_data: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct NfsExport {
#[serde(default = "gen_exp_class_string")]
class: String,
pub id: String,
pub fs_id: String,
pub export_path: String,
pub auth: String,
pub root: Vec<String>,
pub rw: Vec<String>,
pub ro: Vec<String>,
pub anonuid: i64,
pub anongid: i64,
pub options: String,
plugin_data: Option<String>,
}
impl NfsExport {
pub const ANON_UID_GID_NA: i64 = -1;
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AccessGroup {
#[serde(default = "gen_ag_class_string")]
class: String,
pub id: String,
pub name: String,
pub init_ids: Vec<String>,
#[serde(deserialize_with = "int_to_init_type")]
#[serde(serialize_with = "init_type_to_int")]
pub init_type: InitiatorType,
plugin_data: Option<String>,
pub system_id: String,
}
#[repr(i32)]
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum InitiatorType {
Unknown = 0,
Other = 1,
Wwpn = 2,
IscsiIqn = 5,
Mixed = 7,
}
fn int_to_init_type<'de, D: Deserializer<'de>>(
deserializer: D,
) -> ::std::result::Result<InitiatorType, D::Error> {
let i: i32 = Deserialize::deserialize(deserializer)?;
match i {
0 | 1 | 2 | 5 | 7 => unsafe { Ok(transmute::<i32, InitiatorType>(i)) },
_ => Ok(InitiatorType::Unknown),
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn init_type_to_int<S: Serializer>(
i: &InitiatorType,
serializer: S,
) -> ::std::result::Result<S::Ok, S::Error> {
serializer.serialize_i32(*i as i32)
}
#[allow(dead_code)]
#[derive(Deserialize, Debug, Clone)]
pub struct TargetPort {
pub id: String,
#[serde(deserialize_with = "int_to_port_type")]
pub port_type: PortType,
pub service_address: String,
pub network_address: String,
pub physical_address: String,
pub physical_name: String,
plugin_data: Option<String>,
pub system_id: String,
}
#[repr(i32)]
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum PortType {
Other = 1,
Fc = 2,
FCoE = 3,
Iscsi = 4,
}
fn int_to_port_type<'de, D: Deserializer<'de>>(
deserializer: D,
) -> ::std::result::Result<PortType, D::Error> {
let i: i32 = Deserialize::deserialize(deserializer)?;
match i {
1..=4 => unsafe { Ok(transmute::<i32, PortType>(i)) },
_ => Ok(PortType::Other),
}
}
#[allow(dead_code)]
#[derive(Deserialize, Debug, Clone)]
pub struct Battery {
pub id: String,
pub name: String,
#[serde(rename = "type")]
#[serde(deserialize_with = "int_to_battery_type")]
pub battery_type: BatteryType,
pub status: u64,
plugin_data: Option<String>,
pub system_id: String,
}
impl Battery {
pub const STATUS_UNKNOWN: u64 = 1;
pub const STATUS_OTHER: u64 = 1 << 1;
pub const STATUS_OK: u64 = 1 << 2;
pub const STATUS_DISCHARGING: u64 = 1 << 3;
pub const STATUS_CHARGING: u64 = 1 << 4;
pub const STATUS_LEARNING: u64 = 1 << 5;
pub const STATUS_DEGRADED: u64 = 1 << 6;
pub const STATUS_ERROR: u64 = 1 << 7;
}
#[repr(i32)]
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum BatteryType {
Unknown = 1,
Other = 2,
Chemical = 3,
Capacitor = 4,
}
fn int_to_battery_type<'de, D: Deserializer<'de>>(
deserializer: D,
) -> ::std::result::Result<BatteryType, D::Error> {
let i: i32 = Deserialize::deserialize(deserializer)?;
match i {
1..=4 => unsafe { Ok(transmute::<i32, BatteryType>(i)) },
_ => Ok(BatteryType::Unknown),
}
}
#[derive(Deserialize, Debug, Clone)]
pub struct Capabilities {
cap: String,
}
#[repr(usize)]
pub enum Capability {
Volumes = 20,
VolumeCreate = 21,
VolumeResize = 22,
VolumeReplicate = 23,
VolumeReplicateClone = 24,
VolumeReplicateCopy = 25,
VolumeReplicateMirrorAsync = 26,
VolumeReplicateMirrorSync = 27,
VolumeRepRangeBlockSize = 28,
VolumeRepRange = 29,
VolumeRepRangeClone = 30,
VolumeRepRangeCopy = 31,
VolumeDelete = 33,
VolumeEnable = 34,
VolumeDisable = 35,
VolumeMask = 36,
VolumeUnmask = 37,
AccessGroups = 38,
AccessGroupCreateWwpn = 39,
AccessGroupDelete = 40,
AccessGroupInitAddWwpn = 41,
AccessGroupInitDel = 42,
VolsMaskedToAg = 43,
AgsGrantedToVol = 44,
VolHasChildDep = 45,
VolChildDepRm = 46,
AccessGroupCreateIscsiIqn = 47,
AccessGroupInitAddIscsiIqn = 48,
IscsiChapAuthSet = 53,
VolRaidInfo = 54,
VolumeThin = 55,
Batteries = 56,
VolCacheInfo = 57,
VolPhyDiskCacheSet = 58,
VolPhysicalDiskCacheSetSystemLevel = 59,
VolWriteCacheSetEnable = 60,
VolWriteCacheSetAuto = 61,
VolWriteCacheSetDisabled = 62,
VolWriteCacheSetImpactRead = 63,
VolWriteCacheSetWbImpactOther = 64,
VolReadCacheSet = 65,
VolReadCacheSetImpactWrite = 66,
Fs = 100,
FsDelete = 101,
FsResize = 102,
FsCreate = 103,
FsClone = 104,
FsFileClone = 105,
FsSnapshots = 106,
FsSnapshotCreate = 107,
FsSnapshotDelete = 109,
FsSnapshotRestore = 110,
FsSnapshotRestoreSpecificFiles = 111,
FsHasChildDep = 112,
FsChildDepRm = 113,
FsChildDepRmSpecificFiles = 114,
NfsExportAuthTypeList = 120,
NfsExports = 121,
FsExport = 122,
FsUnexport = 123,
FsExportCustomPath = 124,
SysReadCachePctSet = 158,
SysReadCachePctGet = 159,
SysFwVersionGet = 160,
SysModeGet = 161,
DiskLocation = 163,
DiskRpm = 164,
DiskLinkType = 165,
VolumeLed = 171,
TargetPorts = 216,
Disks = 220,
PoolMemberInfo = 221,
VolumeRaidCreate = 222,
DiskVpd83Get = 223,
}
impl Capabilities {
pub fn is_supported(&self, cap: Capability) -> bool {
let cap_num = cap as usize;
let val = &self.cap[cap_num * 2..cap_num * 2 + 2];
println!("val {}", val);
matches!(val, "01")
}
}
#[derive(Serialize, Debug, Clone)]
pub struct BlockRange {
class: String,
#[serde(rename = "src_block")]
src_blk_addr: u64,
#[serde(rename = "dest_block")]
dst_blk_addr: u64,
#[serde(rename = "block_count")]
blk_count: u64,
}
impl BlockRange {
pub fn new(src_blk_addr: u64, dst_blk_addr: u64, blk_count: u64) -> BlockRange {
BlockRange {
class: "BlockRange".to_string(),
src_blk_addr,
dst_blk_addr,
blk_count,
}
}
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum CachePolicy {
Enabled,
Auto, Disabled,
Unknown,
UseDiskSetting, }
#[derive(Debug, Clone)]
pub struct VolumeCacheInfo {
pub write_cache_setting: CachePolicy,
pub write_cache_status: CachePolicy,
pub read_cache_setting: CachePolicy,
pub read_cache_status: CachePolicy,
pub physical_disk_cache_status: CachePolicy,
}
#[derive(Debug, Clone)]
pub struct NfsAccess<'a> {
pub root_list: &'a [&'a str],
pub rw_list: &'a [&'a str],
pub ro_list: &'a [&'a str],
pub anon_uid: Option<i64>,
pub anon_gid: Option<i64>,
}
pub enum VolumeCreateArgThinP {
Full,
Thin,
Default,
}