1 #######################################################################################
2 # Copyright ETSI Contributors and Others.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #######################################################################################
19 from typing
import Dict
, List
21 from azure
.identity
import ClientSecretCredential
22 from azure
.mgmt
.compute
import ComputeManagementClient
23 from azure
.mgmt
.monitor
import MonitorManagementClient
24 from azure
.profiles
import ProfileDefinition
25 from osm_mon
.vim_connectors
.base_vim
import VIMConnector
28 log
= logging
.getLogger(__name__
)
33 "metricname": "Percentage CPU",
34 "aggregation": "Average",
37 "metricname": "Disk Read Operations/Sec",
38 "aggregation": "Average",
41 "metricname": "Disk Write Operations/Sec",
42 "aggregation": "Average",
45 "metricname": "Disk Read Bytes",
46 "aggregation": "Total",
49 "metricname": "Disk Write Bytes",
50 "aggregation": "Total",
52 # "average_memory_utilization": {},
53 # "packets_in_dropped": {},
54 # "packets_out_dropped": {},
55 # "packets_received": {},
60 class AzureCollector(VIMConnector
):
61 # Translate azure provisioning state to OSM provision state.
62 # The first three ones are the transitional status once a user initiated
63 # action has been requested. Once the operation is complete, it will
64 # transition into the states Succeeded or Failed
65 # https://docs.microsoft.com/en-us/azure/virtual-machines/windows/states-lifecycle
66 provision_state2osm
= {
69 "Deleting": "INACTIVE",
70 "Succeeded": "ACTIVE",
74 # Translate azure power state to OSM provision state
76 "starting": "INACTIVE",
78 "stopping": "INACTIVE",
79 "stopped": "INACTIVE",
81 "deallocated": "BUILD",
82 "deallocating": "BUILD",
85 AZURE_COMPUTE_MGMT_CLIENT_API_VERSION
= "2021-03-01"
86 AZURE_COMPUTE_MGMT_PROFILE_TAG
= "azure.mgmt.compute.ComputeManagementClient"
87 AZURE_COMPUTE_MGMT_PROFILE
= ProfileDefinition(
89 AZURE_COMPUTE_MGMT_PROFILE_TAG
: {
90 None: AZURE_COMPUTE_MGMT_CLIENT_API_VERSION
,
91 "availability_sets": "2020-12-01",
92 "dedicated_host_groups": "2020-12-01",
93 "dedicated_hosts": "2020-12-01",
94 "disk_accesses": "2020-12-01",
95 "disk_encryption_sets": "2020-12-01",
96 "disk_restore_point": "2020-12-01",
97 "disks": "2020-12-01",
98 "galleries": "2020-09-30",
99 "gallery_application_versions": "2020-09-30",
100 "gallery_applications": "2020-09-30",
101 "gallery_image_versions": "2020-09-30",
102 "gallery_images": "2020-09-30",
103 "gallery_sharing_profile": "2020-09-30",
104 "images": "2020-12-01",
105 "log_analytics": "2020-12-01",
106 "operations": "2020-12-01",
107 "proximity_placement_groups": "2020-12-01",
108 "resource_skus": "2019-04-01",
109 "shared_galleries": "2020-09-30",
110 "shared_gallery_image_versions": "2020-09-30",
111 "shared_gallery_images": "2020-09-30",
112 "snapshots": "2020-12-01",
113 "ssh_public_keys": "2020-12-01",
114 "usage": "2020-12-01",
115 "virtual_machine_extension_images": "2020-12-01",
116 "virtual_machine_extensions": "2020-12-01",
117 "virtual_machine_images": "2020-12-01",
118 "virtual_machine_images_edge_zone": "2020-12-01",
119 "virtual_machine_run_commands": "2020-12-01",
120 "virtual_machine_scale_set_extensions": "2020-12-01",
121 "virtual_machine_scale_set_rolling_upgrades": "2020-12-01",
122 "virtual_machine_scale_set_vm_extensions": "2020-12-01",
123 "virtual_machine_scale_set_vm_run_commands": "2020-12-01",
124 "virtual_machine_scale_set_vms": "2020-12-01",
125 "virtual_machine_scale_sets": "2020-12-01",
126 "virtual_machine_sizes": "2020-12-01",
127 "virtual_machines": "2020-12-01",
130 AZURE_COMPUTE_MGMT_PROFILE_TAG
+ " osm",
133 def __init__(self
, vim_account
: Dict
):
134 self
.vim_account
= vim_account
135 self
.reload_client
= True
136 logger
= logging
.getLogger("azure")
137 logger
.setLevel(logging
.ERROR
)
138 # Store config to create azure subscription later
140 "user": vim_account
["vim_user"],
141 "passwd": vim_account
["vim_password"],
142 "tenant": vim_account
["vim_tenant_name"],
146 config
= vim_account
["config"]
147 if "subscription_id" in config
:
148 self
._config
["subscription_id"] = config
.get("subscription_id")
149 log
.info("Subscription: %s", self
._config
["subscription_id"])
151 log
.error("Subscription not specified")
155 if "resource_group" in config
:
156 self
.resource_group
= config
.get("resource_group")
158 log
.error("Azure resource_group is not specified at config")
161 def _reload_connection(self
):
162 if self
.reload_client
:
163 log
.debug("reloading azure client")
165 self
.credentials
= ClientSecretCredential(
166 client_id
=self
._config
["user"],
167 client_secret
=self
._config
["passwd"],
168 tenant_id
=self
._config
["tenant"],
170 self
.conn_compute
= ComputeManagementClient(
172 self
._config
["subscription_id"],
173 profile
=self
.AZURE_COMPUTE_MGMT_PROFILE
,
176 self
.conn_monitor
= MonitorManagementClient(
178 self
._config
["subscription_id"],
180 # Set to client created
181 self
.reload_client
= False
182 except Exception as e
:
185 def collect_servers_status(self
) -> List
[Dict
]:
187 log
.debug("collect_servers_status")
188 self
._reload
_connection
()
190 for vm
in self
.conn_compute
.virtual_machines
.list(self
.resource_group
):
192 array
= id.split("/")
194 status
= self
.provision_state2osm
.get(vm
.provisioning_state
, "OTHER")
195 if vm
.provisioning_state
== "Succeeded":
196 # check if machine is running or stopped
197 instance_view
= self
.conn_compute
.virtual_machines
.instance_view(
198 self
.resource_group
, name
200 for status
in instance_view
.statuses
:
201 splitted_status
= status
.code
.split("/")
203 len(splitted_status
) == 2
204 and splitted_status
[0] == "PowerState"
206 status
= self
.power_state2osm
.get(
207 splitted_status
[1], "OTHER"
209 # log.info(f'id: {id}, name: {name}, status: {status}')
213 "status": (1 if (status
== "ACTIVE") else 0),
216 except Exception as e
:
220 def is_vim_ok(self
) -> bool:
222 self
.reload_client
= True
224 self
._reload
_connection
()
226 except Exception as e
:
230 def collect_metrics(self
, metric_list
: List
[Dict
]) -> List
[Dict
]:
231 log
.debug("collect_metrics")
232 self
._reload
_connection
()
235 log
.info(metric_list
)
236 for metric
in metric_list
:
237 server
= metric
["vm_id"]
238 metric_name
= metric
["metric"]
239 metric_mapping
= METRIC_MAPPINGS
.get(metric_name
)
240 if not metric_mapping
:
241 # log.info(f"Metric {metric_name} not available in Azure")
243 azure_metric_name
= metric_mapping
["metricname"]
244 azure_aggregation
= metric_mapping
["aggregation"]
245 end
= datetime
.datetime
.now()
246 init
= end
- datetime
.timedelta(minutes
=5)
248 metrics_data
= self
.conn_monitor
.metrics
.list(
250 timespan
="{}/{}".format(init
, end
),
252 metricnames
=azure_metric_name
,
253 aggregation
=azure_aggregation
,
255 except Exception as e
:
260 for item
in metrics_data
.value
:
261 log
.info("{} ({})".format(item
.name
.localized_value
, item
.unit
))
262 for timeserie
in item
.timeseries
:
263 for data
in timeserie
.data
:
264 if azure_aggregation
== "Average":
266 elif azure_aggregation
== "Total":
270 log
.info("{}: {}".format(data
.time_stamp
, val
))
275 value
= total
/ n_metrics
276 log
.info(f
"value = {value}")
277 metric
["value"] = value
278 metric_results
.append(metric
)
280 log
.info("No metric available")
282 return metric_results