@@ -39,19 +39,97 @@ def get_resource_monitoring() -> Dict[str, Any]:
3939 try :
4040 all_servers = list (conn .compute .servers ())
4141 servers = [s for s in all_servers if getattr (s , 'project_id' , None ) == current_project_id ]
42- hypervisors = list (conn .compute .hypervisors ()) # Hypervisors are cluster-wide
42+
43+ # Calculate actual compute usage from instances
44+ total_used_vcpus = 0
45+ total_used_ram_mb = 0
46+ total_used_disk_gb = 0
47+ running_servers = 0
48+
49+ for server in servers :
50+ if server .status == 'ACTIVE' :
51+ running_servers += 1
52+
53+ # Get resource usage from server's flavor
54+ flavor = server .flavor
55+ if flavor :
56+ # Server flavor is already a flavor object with resource info
57+ vcpus = getattr (flavor , 'vcpus' , 0 ) or 0
58+ ram_mb = getattr (flavor , 'ram' , 0 ) or 0
59+ disk_gb = getattr (flavor , 'disk' , 0 ) or 0
60+ ephemeral_gb = getattr (flavor , 'OS-FLV-EXT-DATA:ephemeral' , 0 ) or 0
61+ swap_gb = getattr (flavor , 'swap' , 0 ) or 0
62+
63+ # Convert swap from MB to GB if it's in MB (some OpenStack versions use MB)
64+ if swap_gb > 100 : # Likely in MB
65+ swap_gb = swap_gb / 1024
66+
67+ total_instance_disk = disk_gb + ephemeral_gb + swap_gb
68+
69+ total_used_vcpus += vcpus
70+ total_used_ram_mb += ram_mb
71+ total_used_disk_gb += total_instance_disk
72+
73+ # Try to get hypervisor totals (physical capacity)
74+ total_physical_vcpus = 0
75+ total_physical_ram_mb = 0
76+ total_physical_disk_gb = 0
77+ hypervisor_count = 0
78+
79+ try :
80+ hypervisors = list (conn .compute .hypervisors ())
81+ hypervisor_count = len (hypervisors )
82+
83+ # Since hypervisor detailed stats are not available in this environment,
84+ # try to get quota limits as a reasonable approximation of capacity
85+ try :
86+ quota = conn .compute .get_quota_set (current_project_id )
87+ # Use quota limits as approximate capacity indicators
88+ if hasattr (quota , 'cores' ) and quota .cores and quota .cores > 0 :
89+ total_physical_vcpus = quota .cores
90+ if hasattr (quota , 'ram' ) and quota .ram and quota .ram > 0 :
91+ total_physical_ram_mb = quota .ram
92+
93+ except Exception as quota_error :
94+ logger .info (f"Could not get quota for capacity estimation: { quota_error } " )
95+
96+ # Alternative: Try to get aggregate/availability zone stats
97+ try :
98+ # Some deployments provide compute service stats
99+ services = list (conn .compute .services (binary = 'nova-compute' ))
100+ if services and hypervisor_count > 0 :
101+ # Rough estimation: assume each compute service represents similar capacity
102+ # This is just a fallback when hypervisor stats aren't available
103+ if total_physical_vcpus == 0 :
104+ # Very rough estimate: if we can't get real data,
105+ # assume some reasonable default per hypervisor
106+ estimated_vcpus_per_hypervisor = max (total_used_vcpus * 2 , 8 ) # At least double usage or 8
107+ total_physical_vcpus = estimated_vcpus_per_hypervisor * hypervisor_count
108+
109+ if total_physical_ram_mb == 0 :
110+ estimated_ram_per_hypervisor = max (total_used_ram_mb * 2 , 16384 ) # At least double usage or 16GB
111+ total_physical_ram_mb = estimated_ram_per_hypervisor * hypervisor_count
112+
113+ except Exception :
114+ pass
115+
116+ except Exception :
117+ # If hypervisor access fails, we'll still show instance usage
118+ pass
43119
44120 compute_stats = {
45121 'total_servers' : len (servers ),
46- 'running_servers' : len ([s for s in servers if s .status == 'ACTIVE' ]),
47- 'total_hypervisors' : len (hypervisors ), # Cluster-wide stat
48- 'total_vcpus' : sum (getattr (h , 'vcpus' , 0 ) for h in hypervisors ), # Cluster-wide stat
49- 'used_vcpus' : sum (getattr (h , 'vcpus_used' , 0 ) for h in hypervisors ), # Cluster-wide stat
50- 'total_memory_mb' : sum (getattr (h , 'memory_mb' , 0 ) for h in hypervisors ), # Cluster-wide stat
51- 'used_memory_mb' : sum (getattr (h , 'memory_mb_used' , 0 ) for h in hypervisors ), # Cluster-wide stat
52- 'total_disk_gb' : sum (getattr (h , 'local_gb' , 0 ) for h in hypervisors ), # Cluster-wide stat
53- 'used_disk_gb' : sum (getattr (h , 'local_gb_used' , 0 ) for h in hypervisors ), # Cluster-wide stat
54- 'project_server_count' : len (servers ) # Project-specific stat
122+ 'running_servers' : running_servers ,
123+ 'total_hypervisors' : hypervisor_count ,
124+ # Physical capacity (from hypervisors)
125+ 'total_vcpus' : total_physical_vcpus ,
126+ 'total_memory_mb' : total_physical_ram_mb ,
127+ 'total_disk_gb' : total_physical_disk_gb ,
128+ # Usage (from instances)
129+ 'used_vcpus' : total_used_vcpus ,
130+ 'used_memory_mb' : total_used_ram_mb ,
131+ 'used_disk_gb' : total_used_disk_gb , # Calculated from instance flavors
132+ 'project_server_count' : len (servers )
55133 }
56134
57135 monitoring_data ['compute' ] = compute_stats
@@ -387,15 +465,24 @@ def get_quota(project_name: str = "") -> Dict[str, Any]:
387465 quota_data = {
388466 'project_name' : project_name ,
389467 'project_id' : project_id ,
390- 'compute' : {},
391- 'network' : {},
392- 'volume' : {}
468+ 'compute' : {
469+ 'limits' : {},
470+ 'usage' : {}
471+ },
472+ 'network' : {
473+ 'limits' : {},
474+ 'usage' : {}
475+ },
476+ 'volume' : {
477+ 'limits' : {},
478+ 'usage' : {}
479+ }
393480 }
394481
395- # Compute quotas
482+ # Compute quotas and usage
396483 try :
397484 compute_quotas = conn .compute .get_quota_set (project_id )
398- quota_data ['compute' ] = {
485+ quota_data ['compute' ][ 'limits' ] = {
399486 'instances' : getattr (compute_quotas , 'instances' , - 1 ),
400487 'cores' : getattr (compute_quotas , 'cores' , - 1 ),
401488 'ram' : getattr (compute_quotas , 'ram' , - 1 ),
@@ -404,13 +491,37 @@ def get_quota(project_name: str = "") -> Dict[str, Any]:
404491 'server_groups' : getattr (compute_quotas , 'server_groups' , - 1 ),
405492 'server_group_members' : getattr (compute_quotas , 'server_group_members' , - 1 )
406493 }
494+
495+ # Get compute usage
496+ instances = list (conn .compute .servers ())
497+ active_instances = [i for i in instances if getattr (i , 'status' , '' ) == 'ACTIVE' ]
498+ total_cores = 0
499+ total_ram = 0
500+
501+ for instance in instances :
502+ try :
503+ flavor = conn .compute .get_flavor (instance .flavor ['id' ])
504+ total_cores += getattr (flavor , 'vcpus' , 0 )
505+ total_ram += getattr (flavor , 'ram' , 0 )
506+ except Exception :
507+ pass
508+
509+ keypairs = list (conn .compute .keypairs ())
510+
511+ quota_data ['compute' ]['usage' ] = {
512+ 'instances' : len (instances ),
513+ 'cores' : total_cores ,
514+ 'ram' : total_ram ,
515+ 'key_pairs' : len (keypairs ),
516+ 'active_instances' : len (active_instances )
517+ }
407518 except Exception as e :
408519 quota_data ['compute' ] = {'error' : str (e )}
409520
410- # Network quotas
521+ # Network quotas and usage
411522 try :
412523 network_quotas = conn .network .get_quota (project_id )
413- quota_data ['network' ] = {
524+ quota_data ['network' ][ 'limits' ] = {
414525 'networks' : getattr (network_quotas , 'networks' , - 1 ),
415526 'subnets' : getattr (network_quotas , 'subnets' , - 1 ),
416527 'ports' : getattr (network_quotas , 'ports' , - 1 ),
@@ -419,19 +530,67 @@ def get_quota(project_name: str = "") -> Dict[str, Any]:
419530 'security_groups' : getattr (network_quotas , 'security_groups' , - 1 ),
420531 'security_group_rules' : getattr (network_quotas , 'security_group_rules' , - 1 )
421532 }
533+
534+ # Get network usage
535+ networks = list (conn .network .networks (project_id = project_id ))
536+ subnets = list (conn .network .subnets (project_id = project_id ))
537+ ports = list (conn .network .ports (project_id = project_id ))
538+ routers = list (conn .network .routers (project_id = project_id ))
539+ floatingips = list (conn .network .ips (project_id = project_id ))
540+ security_groups = list (conn .network .security_groups (project_id = project_id ))
541+
542+ total_sg_rules = 0
543+ for sg in security_groups :
544+ try :
545+ rules = list (conn .network .security_group_rules (security_group_id = sg .id ))
546+ total_sg_rules += len (rules )
547+ except Exception :
548+ pass
549+
550+ quota_data ['network' ]['usage' ] = {
551+ 'networks' : len (networks ),
552+ 'subnets' : len (subnets ),
553+ 'ports' : len (ports ),
554+ 'routers' : len (routers ),
555+ 'floatingips' : len (floatingips ),
556+ 'security_groups' : len (security_groups ),
557+ 'security_group_rules' : total_sg_rules
558+ }
422559 except Exception as e :
423560 quota_data ['network' ] = {'error' : str (e )}
424561
425- # Volume quotas
562+ # Volume quotas and usage
426563 try :
427564 volume_quotas = conn .volume .get_quota_set (project_id )
428- quota_data ['volume' ] = {
565+ quota_data ['volume' ][ 'limits' ] = {
429566 'volumes' : getattr (volume_quotas , 'volumes' , - 1 ),
430567 'snapshots' : getattr (volume_quotas , 'snapshots' , - 1 ),
431568 'gigabytes' : getattr (volume_quotas , 'gigabytes' , - 1 ),
432569 'backups' : getattr (volume_quotas , 'backups' , - 1 ),
433570 'backup_gigabytes' : getattr (volume_quotas , 'backup_gigabytes' , - 1 )
434571 }
572+
573+ # Get volume usage
574+ volumes = list (conn .volume .volumes (project_id = project_id ))
575+ snapshots = list (conn .volume .snapshots (project_id = project_id ))
576+
577+ total_gigabytes = sum (getattr (vol , 'size' , 0 ) for vol in volumes )
578+
579+ # Try to get backups (may not be available in all OpenStack deployments)
580+ try :
581+ backups = list (conn .volume .backups (project_id = project_id ))
582+ backup_gigabytes = sum (getattr (backup , 'size' , 0 ) for backup in backups )
583+ except Exception :
584+ backups = []
585+ backup_gigabytes = 0
586+
587+ quota_data ['volume' ]['usage' ] = {
588+ 'volumes' : len (volumes ),
589+ 'snapshots' : len (snapshots ),
590+ 'gigabytes' : total_gigabytes ,
591+ 'backups' : len (backups ),
592+ 'backup_gigabytes' : backup_gigabytes
593+ }
435594 except Exception as e :
436595 quota_data ['volume' ] = {'error' : str (e )}
437596
0 commit comments