X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=src%2Fosm_mon%2Fvim_connectors%2Fazure.py;fp=src%2Fosm_mon%2Fvim_connectors%2Fazure.py;h=a401f752ac848786a499e85fc736986d7bd0af9a;hb=6683456ee66a599d2685832edbde82e66647b223;hp=0000000000000000000000000000000000000000;hpb=f6ca494310301d21d4455f15fd1779163d43af57;p=osm%2FNG-SA.git diff --git a/src/osm_mon/vim_connectors/azure.py b/src/osm_mon/vim_connectors/azure.py new file mode 100644 index 0000000..a401f75 --- /dev/null +++ b/src/osm_mon/vim_connectors/azure.py @@ -0,0 +1,183 @@ +####################################################################################### +# Copyright ETSI Contributors and Others. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +####################################################################################### +import logging +from typing import Dict, List + +from azure.identity import ClientSecretCredential +from azure.mgmt.compute import ComputeManagementClient +from azure.profiles import ProfileDefinition +from osm_mon.vim_connectors.base_vim import VIMConnector + + +log = logging.getLogger(__name__) + + +class AzureCollector(VIMConnector): + + # Translate azure provisioning state to OSM provision state. + # The first three ones are the transitional status once a user initiated + # action has been requested. Once the operation is complete, it will + # transition into the states Succeeded or Failed + # https://docs.microsoft.com/en-us/azure/virtual-machines/windows/states-lifecycle + provision_state2osm = { + "Creating": "BUILD", + "Updating": "BUILD", + "Deleting": "INACTIVE", + "Succeeded": "ACTIVE", + "Failed": "ERROR", + } + + # Translate azure power state to OSM provision state + power_state2osm = { + "starting": "INACTIVE", + "running": "ACTIVE", + "stopping": "INACTIVE", + "stopped": "INACTIVE", + "unknown": "OTHER", + "deallocated": "BUILD", + "deallocating": "BUILD", + } + + AZURE_COMPUTE_MGMT_CLIENT_API_VERSION = "2021-03-01" + AZURE_COMPUTE_MGMT_PROFILE_TAG = "azure.mgmt.compute.ComputeManagementClient" + AZURE_COMPUTE_MGMT_PROFILE = ProfileDefinition( + { + AZURE_COMPUTE_MGMT_PROFILE_TAG: { + None: AZURE_COMPUTE_MGMT_CLIENT_API_VERSION, + "availability_sets": "2020-12-01", + "dedicated_host_groups": "2020-12-01", + "dedicated_hosts": "2020-12-01", + "disk_accesses": "2020-12-01", + "disk_encryption_sets": "2020-12-01", + "disk_restore_point": "2020-12-01", + "disks": "2020-12-01", + "galleries": "2020-09-30", + "gallery_application_versions": "2020-09-30", + "gallery_applications": "2020-09-30", + "gallery_image_versions": "2020-09-30", + "gallery_images": "2020-09-30", + "gallery_sharing_profile": "2020-09-30", + "images": "2020-12-01", + "log_analytics": "2020-12-01", + "operations": "2020-12-01", + "proximity_placement_groups": "2020-12-01", + "resource_skus": "2019-04-01", + "shared_galleries": "2020-09-30", + "shared_gallery_image_versions": "2020-09-30", + "shared_gallery_images": "2020-09-30", + "snapshots": "2020-12-01", + "ssh_public_keys": "2020-12-01", + "usage": "2020-12-01", + "virtual_machine_extension_images": "2020-12-01", + "virtual_machine_extensions": "2020-12-01", + "virtual_machine_images": "2020-12-01", + "virtual_machine_images_edge_zone": "2020-12-01", + "virtual_machine_run_commands": "2020-12-01", + "virtual_machine_scale_set_extensions": "2020-12-01", + "virtual_machine_scale_set_rolling_upgrades": "2020-12-01", + "virtual_machine_scale_set_vm_extensions": "2020-12-01", + "virtual_machine_scale_set_vm_run_commands": "2020-12-01", + "virtual_machine_scale_set_vms": "2020-12-01", + "virtual_machine_scale_sets": "2020-12-01", + "virtual_machine_sizes": "2020-12-01", + "virtual_machines": "2020-12-01", + } + }, + AZURE_COMPUTE_MGMT_PROFILE_TAG + " osm", + ) + + def __init__(self, vim_account: Dict): + self.vim_account = vim_account + self.reload_client = True + logger = logging.getLogger("azure") + logger.setLevel(logging.ERROR) + # Store config to create azure subscription later + self._config = { + "user": vim_account["vim_user"], + "passwd": vim_account["vim_password"], + "tenant": vim_account["vim_tenant_name"], + } + + # SUBSCRIPTION + config = vim_account["config"] + if "subscription_id" in config: + self._config["subscription_id"] = config.get("subscription_id") + log.info("Subscription: %s", self._config["subscription_id"]) + else: + log.error("Subscription not specified") + return + + # RESOURCE_GROUP + if "resource_group" in config: + self.resource_group = config.get("resource_group") + else: + log.error("Azure resource_group is not specified at config") + return + + def _reload_connection(self): + if self.reload_client: + log.debug("reloading azure client") + try: + self.credentials = ClientSecretCredential( + client_id=self._config["user"], + client_secret=self._config["passwd"], + tenant_id=self._config["tenant"], + ) + self.conn_compute = ComputeManagementClient( + self.credentials, + self._config["subscription_id"], + profile=self.AZURE_COMPUTE_MGMT_PROFILE, + ) + # Set to client created + self.reload_client = False + except Exception as e: + log.error(e) + + def collect_servers_status(self) -> List[Dict]: + servers = [] + log.debug("collect_servers_status") + self._reload_connection() + try: + for vm in self.conn_compute.virtual_machines.list(self.resource_group): + id = vm.id + array = id.split("/") + name = array[-1] + status = self.provision_state2osm.get(vm.provisioning_state, "OTHER") + if vm.provisioning_state == "Succeeded": + # check if machine is running or stopped + instance_view = self.conn_compute.virtual_machines.instance_view( + self.resource_group, name + ) + for status in instance_view.statuses: + splitted_status = status.code.split("/") + if ( + len(splitted_status) == 2 + and splitted_status[0] == "PowerState" + ): + status = self.power_state2osm.get( + splitted_status[1], "OTHER" + ) + # log.info(f'id: {id}, name: {name}, status: {status}') + vm = { + "id": id, + "name": name, + "status": (1 if (status == "ACTIVE") else 0), + } + servers.append(vm) + except Exception as e: + log.error(e) + return servers