Skip to content

Commit

Permalink
add subcapacities for Cinder pools
Browse files Browse the repository at this point in the history
  • Loading branch information
majewsky committed Jun 5, 2023
1 parent c2a70f5 commit adc372d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 15 deletions.
37 changes: 25 additions & 12 deletions internal/plugins/capacity_cinder.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ type capacityCinderPlugin struct {
VolumeBackendName string `yaml:"volume_backend_name"`
IsDefault bool `yaml:"default"`
} `yaml:"volume_types"`
//computed state
reportSubcapacities map[string]bool `yaml:"-"`
//connections
CinderV3 *gophercloud.ServiceClient `yaml:"-"`
}
Expand All @@ -51,6 +53,8 @@ func init() {

// Init implements the core.CapacityPlugin interface.
func (p *capacityCinderPlugin) Init(provider *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, scrapeSubcapacities map[string]map[string]bool) (err error) {
p.reportSubcapacities = scrapeSubcapacities["volumev2"]

if len(p.VolumeTypes) == 0 {
//nolint:stylecheck //Cinder is a proper name
return errors.New("Cinder capacity plugin: missing required configuration field cinder.volume_types")
Expand Down Expand Up @@ -133,49 +137,58 @@ func (p *capacityCinderPlugin) Scrape() (result map[string]map[string]core.Capac
}

//add results from scheduler-stats
for _, element := range poolData.StoragePools {
for _, pool := range poolData.StoragePools {
//do not consider pools that are slated for decommissioning (state "drain")
//or reserved for absorbing payloads from draining pools (state "reserved")
//(no quota should be given out for such capacity)
state := element.Capabilities.CustomAttributes.CinderState
state := pool.Capabilities.CustomAttributes.CinderState
if state == "drain" || state == "reserved" {
logg.Info("Cinder capacity plugin: skipping pool %q with %g GiB capacity because of cinder_state %q",
element.Name, element.Capabilities.TotalCapacityGB, state)
pool.Name, pool.Capabilities.TotalCapacityGB, state)
continue
}

volumeType, ok := volumeTypesByBackendName[element.Capabilities.VolumeBackendName]
volumeType, ok := volumeTypesByBackendName[pool.Capabilities.VolumeBackendName]
if !ok {
logg.Info("Cinder capacity plugin: skipping pool %q with unknown volume_backend_name %q", element.Name, element.Capabilities.VolumeBackendName)
logg.Info("Cinder capacity plugin: skipping pool %q with unknown volume_backend_name %q", pool.Name, pool.Capabilities.VolumeBackendName)
continue
}

logg.Debug("Cinder capacity plugin: considering pool %q with volume_backend_name %q for volume type %q", element.Name, element.Capabilities.VolumeBackendName, volumeType)
logg.Debug("Cinder capacity plugin: considering pool %q with volume_backend_name %q for volume type %q", pool.Name, pool.Capabilities.VolumeBackendName, volumeType)

resourceName := p.makeResourceName(volumeType)
capaData[resourceName].Capacity += uint64(element.Capabilities.TotalCapacityGB)
capaData[resourceName].Capacity += uint64(pool.Capabilities.TotalCapacityGB)

var poolAZ string
for az, hosts := range serviceHostsPerAZ {
for _, v := range hosts {
//element.Name has the format backendHostname@backendName#backendPoolName
if strings.Contains(element.Name, v) {
//pool.Name has the format backendHostname@backendName#backendPoolName
if strings.Contains(pool.Name, v) {
poolAZ = az
break
}
}
}
if poolAZ == "" {
logg.Info("Cinder storage pool %q does not match any service host", element.Name)
logg.Info("Cinder storage pool %q does not match any service host", pool.Name)
poolAZ = "unknown"
}
if _, ok := capaData[resourceName].CapacityPerAZ[poolAZ]; !ok {
capaData[resourceName].CapacityPerAZ[poolAZ] = &core.CapacityDataForAZ{}
}

azCapaData := capaData[resourceName].CapacityPerAZ[poolAZ]
azCapaData.Capacity += uint64(element.Capabilities.TotalCapacityGB)
azCapaData.Usage += uint64(element.Capabilities.AllocatedCapacityGB)
azCapaData.Capacity += uint64(pool.Capabilities.TotalCapacityGB)
azCapaData.Usage += uint64(pool.Capabilities.AllocatedCapacityGB)

if p.reportSubcapacities["capacity"] {
capaData[resourceName].Subcapacities = append(capaData[resourceName].Subcapacities, storagePoolSubcapacity{
PoolName: pool.Name,
AvailabilityZone: poolAZ,
CapacityGiB: uint64(pool.Capabilities.TotalCapacityGB),
UsageGiB: uint64(pool.Capabilities.AllocatedCapacityGB),
})
}
}

capaDataFinal := make(map[string]core.CapacityData)
Expand Down
7 changes: 4 additions & 3 deletions internal/plugins/capacity_manila.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ type capacityManilaPlugin struct {
ManilaV2 *gophercloud.ServiceClient `yaml:"-"`
}

type manilaSubcapacity struct {
// This type is shared with the Cinder capacitor.
type storagePoolSubcapacity struct {
PoolName string `json:"pool_name"`
AvailabilityZone string `json:"az"`
CapacityGiB uint64 `json:"capacity_gib"`
Expand Down Expand Up @@ -202,15 +203,15 @@ func (p *capacityManilaPlugin) scrapeForShareType(shareType ManilaShareTypeSpec,
allocatedCapacityGbPerAZ[poolAZ] += pool.Capabilities.AllocatedCapacityGB

if p.reportSubcapacities["share_capacity"] {
shareSubcapacities = append(shareSubcapacities, manilaSubcapacity{
shareSubcapacities = append(shareSubcapacities, storagePoolSubcapacity{
PoolName: pool.Name,
AvailabilityZone: poolAZ,
CapacityGiB: getShareCapacity(pool.Capabilities.TotalCapacityGB, capBalance),
UsageGiB: getShareCapacity(pool.Capabilities.AllocatedCapacityGB, capBalance),
})
}
if p.reportSubcapacities["snapshot_capacity"] {
snapshotSubcapacities = append(snapshotSubcapacities, manilaSubcapacity{
snapshotSubcapacities = append(snapshotSubcapacities, storagePoolSubcapacity{
PoolName: pool.Name,
AvailabilityZone: poolAZ,
CapacityGiB: getSnapshotCapacity(pool.Capabilities.TotalCapacityGB, capBalance),
Expand Down

0 comments on commit adc372d

Please sign in to comment.