Deb package creation for NG-SA
[osm/NG-SA.git] / src / osm_ngsa / osm_mon / vim_connectors / azure.py
1 #######################################################################################
2 # Copyright ETSI Contributors and Others.
3 #
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
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
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
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #######################################################################################
17 import logging
18 from typing import Dict, List
19
20 from azure.identity import ClientSecretCredential
21 from azure.mgmt.compute import ComputeManagementClient
22 from azure.profiles import ProfileDefinition
23 from osm_mon.vim_connectors.base_vim import VIMConnector
24
25
26 log = logging.getLogger(__name__)
27
28
29 class AzureCollector(VIMConnector):
30
31 # Translate azure provisioning state to OSM provision state.
32 # The first three ones are the transitional status once a user initiated
33 # action has been requested. Once the operation is complete, it will
34 # transition into the states Succeeded or Failed
35 # https://docs.microsoft.com/en-us/azure/virtual-machines/windows/states-lifecycle
36 provision_state2osm = {
37 "Creating": "BUILD",
38 "Updating": "BUILD",
39 "Deleting": "INACTIVE",
40 "Succeeded": "ACTIVE",
41 "Failed": "ERROR",
42 }
43
44 # Translate azure power state to OSM provision state
45 power_state2osm = {
46 "starting": "INACTIVE",
47 "running": "ACTIVE",
48 "stopping": "INACTIVE",
49 "stopped": "INACTIVE",
50 "unknown": "OTHER",
51 "deallocated": "BUILD",
52 "deallocating": "BUILD",
53 }
54
55 AZURE_COMPUTE_MGMT_CLIENT_API_VERSION = "2021-03-01"
56 AZURE_COMPUTE_MGMT_PROFILE_TAG = "azure.mgmt.compute.ComputeManagementClient"
57 AZURE_COMPUTE_MGMT_PROFILE = ProfileDefinition(
58 {
59 AZURE_COMPUTE_MGMT_PROFILE_TAG: {
60 None: AZURE_COMPUTE_MGMT_CLIENT_API_VERSION,
61 "availability_sets": "2020-12-01",
62 "dedicated_host_groups": "2020-12-01",
63 "dedicated_hosts": "2020-12-01",
64 "disk_accesses": "2020-12-01",
65 "disk_encryption_sets": "2020-12-01",
66 "disk_restore_point": "2020-12-01",
67 "disks": "2020-12-01",
68 "galleries": "2020-09-30",
69 "gallery_application_versions": "2020-09-30",
70 "gallery_applications": "2020-09-30",
71 "gallery_image_versions": "2020-09-30",
72 "gallery_images": "2020-09-30",
73 "gallery_sharing_profile": "2020-09-30",
74 "images": "2020-12-01",
75 "log_analytics": "2020-12-01",
76 "operations": "2020-12-01",
77 "proximity_placement_groups": "2020-12-01",
78 "resource_skus": "2019-04-01",
79 "shared_galleries": "2020-09-30",
80 "shared_gallery_image_versions": "2020-09-30",
81 "shared_gallery_images": "2020-09-30",
82 "snapshots": "2020-12-01",
83 "ssh_public_keys": "2020-12-01",
84 "usage": "2020-12-01",
85 "virtual_machine_extension_images": "2020-12-01",
86 "virtual_machine_extensions": "2020-12-01",
87 "virtual_machine_images": "2020-12-01",
88 "virtual_machine_images_edge_zone": "2020-12-01",
89 "virtual_machine_run_commands": "2020-12-01",
90 "virtual_machine_scale_set_extensions": "2020-12-01",
91 "virtual_machine_scale_set_rolling_upgrades": "2020-12-01",
92 "virtual_machine_scale_set_vm_extensions": "2020-12-01",
93 "virtual_machine_scale_set_vm_run_commands": "2020-12-01",
94 "virtual_machine_scale_set_vms": "2020-12-01",
95 "virtual_machine_scale_sets": "2020-12-01",
96 "virtual_machine_sizes": "2020-12-01",
97 "virtual_machines": "2020-12-01",
98 }
99 },
100 AZURE_COMPUTE_MGMT_PROFILE_TAG + " osm",
101 )
102
103 def __init__(self, vim_account: Dict):
104 self.vim_account = vim_account
105 self.reload_client = True
106 logger = logging.getLogger("azure")
107 logger.setLevel(logging.ERROR)
108 # Store config to create azure subscription later
109 self._config = {
110 "user": vim_account["vim_user"],
111 "passwd": vim_account["vim_password"],
112 "tenant": vim_account["vim_tenant_name"],
113 }
114
115 # SUBSCRIPTION
116 config = vim_account["config"]
117 if "subscription_id" in config:
118 self._config["subscription_id"] = config.get("subscription_id")
119 log.info("Subscription: %s", self._config["subscription_id"])
120 else:
121 log.error("Subscription not specified")
122 return
123
124 # RESOURCE_GROUP
125 if "resource_group" in config:
126 self.resource_group = config.get("resource_group")
127 else:
128 log.error("Azure resource_group is not specified at config")
129 return
130
131 def _reload_connection(self):
132 if self.reload_client:
133 log.debug("reloading azure client")
134 try:
135 self.credentials = ClientSecretCredential(
136 client_id=self._config["user"],
137 client_secret=self._config["passwd"],
138 tenant_id=self._config["tenant"],
139 )
140 self.conn_compute = ComputeManagementClient(
141 self.credentials,
142 self._config["subscription_id"],
143 profile=self.AZURE_COMPUTE_MGMT_PROFILE,
144 )
145 # Set to client created
146 self.reload_client = False
147 except Exception as e:
148 log.error(e)
149
150 def collect_servers_status(self) -> List[Dict]:
151 servers = []
152 log.debug("collect_servers_status")
153 self._reload_connection()
154 try:
155 for vm in self.conn_compute.virtual_machines.list(self.resource_group):
156 id = vm.id
157 array = id.split("/")
158 name = array[-1]
159 status = self.provision_state2osm.get(vm.provisioning_state, "OTHER")
160 if vm.provisioning_state == "Succeeded":
161 # check if machine is running or stopped
162 instance_view = self.conn_compute.virtual_machines.instance_view(
163 self.resource_group, name
164 )
165 for status in instance_view.statuses:
166 splitted_status = status.code.split("/")
167 if (
168 len(splitted_status) == 2
169 and splitted_status[0] == "PowerState"
170 ):
171 status = self.power_state2osm.get(
172 splitted_status[1], "OTHER"
173 )
174 # log.info(f'id: {id}, name: {name}, status: {status}')
175 vm = {
176 "id": id,
177 "name": name,
178 "status": (1 if (status == "ACTIVE") else 0),
179 }
180 servers.append(vm)
181 except Exception as e:
182 log.error(e)
183 return servers
184
185 def is_vim_ok(self) -> bool:
186 status = False
187 self.reload_client = True
188 try:
189 self._reload_connection()
190 status = True
191 except Exception as e:
192 log.error(e)
193 return status