import logging
import unittest
+import cinderclient.exceptions as cExceptions
from mock import MagicMock, patch
+from neutronclient.common import exceptions as neExceptions
from novaclient import exceptions as nvExceptions
from novaclient.exceptions import ClientException, Conflict
from osm_ro_plugin.vimconn import (
VimConnConnectionException,
VimConnException,
VimConnNotFoundException,
+ VimConnUnexpectedResponse,
)
from osm_rovim_openstack.vimconn_openstack import vimconnector
+from requests.exceptions import ConnectionError
__author__ = "Igor D.C."
__date__ = "$23-aug-2017 23:59:59$"
@patch.object(vimconnector, "update_block_device_mapping")
def test_new_shared_volumes(self, mock_update_block_device_mapping):
"""Create shared volume."""
- self.vimconn.cinder = CopyingMock()
- self.vimconn.cinder.volumes.create.return_value.id = volume_id4
- shared_volume_data = {"size": 10, "name": "shared-volume"}
- self.vimconn.cinder.volumes.create.side_effect = [
- Volume("avaible", "multiattach", "shared-volume", volume_id4)
- ]
+
+ class MyVolume:
+ name = "my-shared-volume"
+ id = volume_id4
+
+ self.vimconn.cinder.volumes.create.return_value = MyVolume()
+ shared_volume_data = {"size": 10, "name": "my-shared-volume"}
result = self.vimconn.new_shared_volumes(shared_volume_data)
self.vimconn.cinder.volumes.create.assert_called_once_with(
- size=10, name="shared-volume", volume_type="multiattach"
+ size=10, name="my-shared-volume", volume_type="multiattach"
)
- self.assertEqual(result[0], "shared-volume")
+ self.assertEqual(result[0], "my-shared-volume")
self.assertEqual(result[1], volume_id4)
@patch.object(vimconnector, "update_block_device_mapping")
},
)
- def test_delete_floating_ip_by_id_floating_ip_raises_nvexception(self):
+ def test_delete_floating_ip_by_id__delete_floating_ip_raises_client_exception__operation_is_successful(
+ self,
+ ):
"""netron delete floating ip raises nvExceptions.ClientException."""
created_items = {
f"floating_ip:{floating_network_vim_id}": True,
"Error deleting floating ip: ClientException: Unknown Error (HTTP Client exception occurred.)"
)
- def test_delete_floating_ip_by_id_floating_ip_raises_vimconnexception(self):
+ def test_delete_floating_ip_by_id__delete_floating_ip_raises_connection_error__operation_fails(
+ self,
+ ):
+ """netron delete floating ip raises nvExceptions.ClientException."""
+ created_items = {
+ f"floating_ip:{floating_network_vim_id}": True,
+ f"port:{port_id}": True,
+ }
+ k_id = floating_network_vim_id
+ k = f"floating_ip:{floating_network_vim_id}"
+ self.vimconn.neutron.delete_floatingip.side_effect = ConnectionError(
+ "Connection exception occurred."
+ )
+ with self.assertRaises(VimConnConnectionException):
+ self.vimconn._delete_floating_ip_by_id(k, k_id, created_items)
+ self.vimconn.neutron.delete_floatingip.assert_called_once_with(k_id)
+ self.assertEqual(
+ created_items,
+ {
+ f"floating_ip:{floating_network_vim_id}": True,
+ f"port:{port_id}": True,
+ },
+ )
+ self.vimconn.logger.error.assert_called_once_with(
+ "Error deleting floating ip: ConnectionError: Connection exception occurred."
+ )
+
+ def test_delete_floating_ip_by_id_floating_ip_raises_vimconn_not_found_exception__operation_is_successful(
+ self,
+ ):
"""netron delete floating ip raises VimConnNotFoundException."""
created_items = {
f"floating_ip:{floating_network_vim_id}": True,
)
self.assertEqual(created_items, expected_created_items)
- def test_delete_volumes_by_id_with_cinder_delete_volume_raise_exception(self):
+ def test_delete_volumes_by_id_with_cinder__delete_volume_raise_client_exception__exception_is_not_raised(
+ self,
+ ):
"""cinder delete volume raises exception."""
created_items = {
f"floating_ip:{floating_network_vim_id}": True,
k = f"volume:{volume_id}"
k_id = volume_id
self.vimconn.cinder.volumes.get.return_value.status = "available"
- self.vimconn.cinder.volumes.delete.side_effect = nvExceptions.ClientException(
- "Connection aborted."
+ self.vimconn.cinder.volumes.delete.side_effect = cExceptions.ClientException(
+ 403, "Connection aborted."
)
result = self.vimconn._delete_volumes_by_id_wth_cinder(
k, k_id, volumes_to_hold, created_items
self.vimconn.cinder.volumes.get.assert_called_once_with(k_id)
self.vimconn.cinder.volumes.delete.assert_called_once_with(k_id)
self.vimconn.logger.error.assert_called_once_with(
- "Error deleting volume: ClientException: Unknown Error (HTTP Connection aborted.)"
+ "Error deleting volume: ClientException: Connection aborted. (HTTP 403)"
+ )
+ self.assertEqual(created_items, expected_created_items)
+
+ def test_delete_volumes_by_id_with_cinder__delete_volume_raise_connection_exception__exception_is_raised(
+ self,
+ ):
+ """cinder delete volume raises exception."""
+ created_items = {
+ f"floating_ip:{floating_network_vim_id}": True,
+ f"volume:{volume_id2}": True,
+ f"volume:{volume_id}": True,
+ f"port:{port_id}": None,
+ }
+ expected_created_items = {
+ f"floating_ip:{floating_network_vim_id}": True,
+ f"volume:{volume_id2}": True,
+ f"volume:{volume_id}": True,
+ f"port:{port_id}": None,
+ }
+ volumes_to_hold = []
+ k = f"volume:{volume_id}"
+ k_id = volume_id
+ self.vimconn.cinder.volumes.get.return_value.status = "available"
+ self.vimconn.cinder.volumes.delete.side_effect = cExceptions.ConnectionError(
+ "Connection failed."
+ )
+ with self.assertRaises(VimConnConnectionException):
+ result = self.vimconn._delete_volumes_by_id_wth_cinder(
+ k, k_id, volumes_to_hold, created_items
+ )
+ self.assertEqual(result, None)
+ self.vimconn.cinder.volumes.get.assert_called_once_with(k_id)
+ self.vimconn.cinder.volumes.delete.assert_called_once_with(k_id)
+ self.vimconn.logger.error.assert_called_once_with(
+ "Error deleting volume: ConnectionError: Connection failed."
)
self.assertEqual(created_items, expected_created_items)
result = self.vimconn._delete_volumes_by_id_wth_cinder(
k, k_id, volumes_to_hold, created_items
)
- self.assertEqual(result, None)
+ self.assertEqual(result, False)
self.vimconn.cinder.volumes.get.assert_not_called()
self.vimconn.cinder.volumes.delete.assert_not_called()
self.vimconn.logger.error.assert_not_called()
@patch.object(vimconnector, "_get_item_name_id")
@patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
@patch.object(vimconnector, "_delete_floating_ip_by_id")
- def test_delete_created_items_delete_vol_raises(
+ def test_delete_created_items__delete_vol_raises_connection_error__operation_fails(
self,
mock_delete_floating_ip_by_id,
mock_delete_volumes_by_id_wth_cinder,
("floating_ip", f"{floating_network_vim_id}"),
("volume", f"{volume_id}"),
]
- mock_delete_volumes_by_id_wth_cinder.side_effect = ConnectionError(
- "Connection failed."
+ mock_delete_volumes_by_id_wth_cinder.side_effect = (
+ neExceptions.ConnectionFailed("Connection failed.")
)
volumes_to_hold = []
keep_waiting = False
- result = self.vimconn._delete_created_items(
- created_items, volumes_to_hold, keep_waiting
- )
- self.assertEqual(result, False)
+ with self.assertRaises(VimConnConnectionException):
+ result = self.vimconn._delete_created_items(
+ created_items, volumes_to_hold, keep_waiting
+ )
+ self.assertEqual(result, None)
self.assertEqual(mock_get_item_name_id.call_count, 2)
mock_delete_volumes_by_id_wth_cinder.assert_called_once_with(
f"volume:{volume_id}", f"{volume_id}", [], created_items
@patch.object(vimconnector, "_get_item_name_id")
@patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
@patch.object(vimconnector, "_delete_floating_ip_by_id")
- def test_delete_created_items_delete_fip_raises(
+ def test_delete_created_items__delete_fip_raises_connection_error__operation_fails(
self,
mock_delete_floating_ip_by_id,
mock_delete_volumes_by_id_wth_cinder,
)
volumes_to_hold = []
keep_waiting = True
- result = self.vimconn._delete_created_items(
- created_items, volumes_to_hold, keep_waiting
- )
- self.assertEqual(result, True)
- self.assertEqual(mock_get_item_name_id.call_count, 2)
- mock_delete_volumes_by_id_wth_cinder.assert_called_once_with(
- f"volume:{volume_id}", f"{volume_id}", [], created_items
- )
+ with self.assertRaises(VimConnConnectionException):
+ result = self.vimconn._delete_created_items(
+ created_items, volumes_to_hold, keep_waiting
+ )
+ self.assertEqual(result, None)
+ self.assertEqual(mock_get_item_name_id.call_count, 1)
+ mock_delete_volumes_by_id_wth_cinder.assert_not_called()
mock_delete_floating_ip_by_id.assert_called_once_with(
f"floating_ip:{floating_network_vim_id}",
f"{floating_network_vim_id}",
@patch.object(vimconnector, "_get_item_name_id")
@patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
@patch.object(vimconnector, "_delete_floating_ip_by_id")
- def test_delete_created_items_get_item_name_raises(
+ def test_delete_created_items_get_item_name_raises_type_error__operation_fails(
self,
mock_delete_floating_ip_by_id,
mock_delete_volumes_by_id_wth_cinder,
]
volumes_to_hold = []
keep_waiting = False
- result = self.vimconn._delete_created_items(
- created_items, volumes_to_hold, keep_waiting
- )
- self.assertEqual(result, False)
- self.assertEqual(mock_get_item_name_id.call_count, 2)
+ with self.assertRaises(VimConnException):
+ result = self.vimconn._delete_created_items(
+ created_items, volumes_to_hold, keep_waiting
+ )
+ self.assertEqual(result, None)
+ self.assertEqual(mock_get_item_name_id.call_count, 1)
mock_delete_volumes_by_id_wth_cinder.assert_not_called()
mock_delete_floating_ip_by_id.assert_not_called()
_call_logger = self.vimconn.logger.error.call_args_list
self.assertEqual(_call_logger[0][0], ("Error deleting 3: Invalid Type",))
- self.assertEqual(
- _call_logger[1][0],
- (f"Error deleting volume{volume_id}: Invalid attribute",),
- )
@patch.object(vimconnector, "_get_item_name_id")
@patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
@patch("time.sleep")
@patch.object(vimconnector, "_extract_items_wth_keep_flag_from_created_items")
- @patch.object(vimconnector, "_format_exception")
@patch.object(vimconnector, "_reload_connection")
@patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
@patch.object(vimconnector, "_delete_created_items")
- def test_delete_vminstance_extract_items_wth_keep_raises(
+ def test_delete_vminstance__extract_items_wth_keep_raises_attributeerror__raise_vimconnexception(
self,
mock_delete_created_items,
mock_delete_vm_ports_attached_to_network,
mock_reload_connection,
- mock_format_exception,
mock_extract_items_wth_keep_flag_from_created_items,
mock_sleep,
):
mock_extract_items_wth_keep_flag_from_created_items.side_effect = AttributeError
volumes_to_hold = []
mock_delete_created_items.return_value = False
- with self.assertRaises(AttributeError):
+ with self.assertRaises(VimConnException):
self.vimconn.delete_vminstance(
vm_id, initial_created_items, volumes_to_hold
)
self.vimconn.nova.servers.delete.assert_not_called()
mock_delete_created_items.assert_not_called()
mock_sleep.assert_not_called()
- mock_format_exception.assert_not_called()
mock_extract_items_wth_keep_flag_from_created_items.assert_called_once_with(
initial_created_items
)
@patch.object(vimconnector, "_reload_connection")
@patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
@patch.object(vimconnector, "_delete_created_items")
- def test_delete_vminstance_delete_created_items_raises(
+ def test_delete_vminstance__delete_created_items_returns_true__delete_created_items_called_several_times(
self,
mock_delete_created_items,
mock_delete_vm_ports_attached_to_network,
mock_extract_items_wth_keep_flag_from_created_items.return_value = created_items
mock_sleep = MagicMock()
volumes_to_hold = []
- err = ConnectionError("ClientException occurred.")
- mock_delete_created_items.side_effect = err
- with self.assertRaises(ConnectionError) as err:
- self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
- self.assertEqual(str(err), "ClientException occurred.")
+ mock_delete_created_items.side_effect = [True, False]
+ self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
mock_reload_connection.assert_called_once()
mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
self.vimconn.nova.servers.delete.assert_called_once_with(vm_id)
- mock_delete_created_items.assert_called_once()
+ self.assertEqual(mock_delete_created_items.call_count, 2)
mock_sleep.assert_not_called()
mock_extract_items_wth_keep_flag_from_created_items.assert_called_once_with(
created_items
@patch("time.sleep")
@patch.object(vimconnector, "_extract_items_wth_keep_flag_from_created_items")
- @patch.object(vimconnector, "_format_exception")
@patch.object(vimconnector, "_reload_connection")
@patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
@patch.object(vimconnector, "_delete_created_items")
- def test_delete_vminstance_delete_vm_ports_raises(
+ def test_delete_vminstance__delete_vm_ports_raises_connection_error__raise_vimconnconnectionexception(
self,
mock_delete_created_items,
mock_delete_vm_ports_attached_to_network,
mock_reload_connection,
- mock_format_exception,
mock_extract_items_wth_keep_flag_from_created_items,
mock_sleep,
):
volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
err = ConnectionError("ClientException occurred.")
mock_delete_vm_ports_attached_to_network.side_effect = err
- mock_delete_created_items.side_effect = err
- with self.assertRaises(ConnectionError) as err:
+ mock_delete_created_items.return_value = False
+ with self.assertRaises(VimConnConnectionException):
self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
- self.assertEqual(str(err), "ClientException occurred.")
mock_reload_connection.assert_called_once()
mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
self.vimconn.nova.servers.delete.assert_not_called()
@patch("time.sleep")
@patch.object(vimconnector, "_extract_items_wth_keep_flag_from_created_items")
- @patch.object(vimconnector, "_format_exception")
@patch.object(vimconnector, "_reload_connection")
@patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
@patch.object(vimconnector, "_delete_created_items")
- def test_delete_vminstance_nova_server_delete_raises(
+ def test_delete_vminstance__nova_server_delete_raises_clientexception__raise_vimconn_unexpected_response(
self,
mock_delete_created_items,
mock_delete_vm_ports_attached_to_network,
mock_reload_connection,
- mock_format_exception,
mock_extract_items_wth_keep_flag_from_created_items,
mock_sleep,
):
created_items = deepcopy(created_items_all_true)
mock_extract_items_wth_keep_flag_from_created_items.return_value = created_items
volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
- err = VimConnConnectionException("ClientException occurred.")
+ err = nvExceptions.ClientException("ClientException occurred.")
self.vimconn.nova.servers.delete.side_effect = err
mock_delete_created_items.side_effect = err
- with self.assertRaises(VimConnConnectionException) as err:
+ with self.assertRaises(VimConnUnexpectedResponse):
self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
- self.assertEqual(str(err), "ClientException occurred.")
mock_reload_connection.assert_called_once()
mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
self.vimconn.nova.servers.delete.assert_called_once_with(vm_id)
@patch("time.sleep")
@patch.object(vimconnector, "_extract_items_wth_keep_flag_from_created_items")
- @patch.object(vimconnector, "_format_exception")
@patch.object(vimconnector, "_reload_connection")
@patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
@patch.object(vimconnector, "_delete_created_items")
- def test_delete_vminstance_reload_connection_raises(
+ def test_delete_vminstance__reload_connection_raises_connection_error__raises_vimconnconnection_exception(
self,
mock_delete_created_items,
mock_delete_vm_ports_attached_to_network,
mock_reload_connection,
- mock_format_exception,
mock_extract_items_wth_keep_flag_from_created_items,
mock_sleep,
):
err = ConnectionError("ClientException occurred.")
mock_delete_created_items.return_value = False
mock_reload_connection.side_effect = err
- with self.assertRaises(ConnectionError) as err:
+ with self.assertRaises(VimConnConnectionException):
self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
- self.assertEqual(str(err), "ClientException occurred.")
mock_reload_connection.assert_called_once()
mock_delete_vm_ports_attached_to_network.assert_not_called()
self.vimconn.nova.servers.delete.assert_not_called()
from typing import Dict, List, Optional, Tuple
from cinderclient import client as cClient
+import cinderclient.exceptions as cExceptions
from glanceclient import client as glClient
import glanceclient.exc as gl1Exceptions
from keystoneauth1 import session
server_timeout = 1800
+def catch_any_exception(func):
+ def format_exception(*args, **kwargs):
+ try:
+ return func(*args, *kwargs)
+ except Exception as e:
+ vimconnector._format_exception(e)
+
+ return format_exception
+
+
class SafeDumper(yaml.SafeDumper):
def represent_data(self, data):
# Openstack APIs use custom subclasses of dict and YAML safe dumper
# Types. Also, abstract vimconnector should call the validation
# method before the implemented VIM connectors are called.
- def _format_exception(self, exception):
+ @staticmethod
+ def _format_exception(exception):
"""Transform a keystone, nova, neutron exception into a vimconn exception discovering the cause"""
message_error = str(exception)
tip = ""
(
neExceptions.NetworkNotFoundClient,
nvExceptions.NotFound,
+ nvExceptions.ResourceNotFound,
ksExceptions.NotFound,
gl1Exceptions.HTTPNotFound,
+ cExceptions.NotFound,
),
):
raise vimconn.VimConnNotFoundException(
ConnectionError,
ksExceptions.ConnectionError,
neExceptions.ConnectionFailed,
+ cExceptions.ConnectionError,
),
):
if type(exception).__name__ == "SSLError":
KeyError,
nvExceptions.BadRequest,
ksExceptions.BadRequest,
+ gl1Exceptions.BadRequest,
+ cExceptions.BadRequest,
),
):
if message_error == "OS-EXT-SRV-ATTR:host":
nvExceptions.ClientException,
ksExceptions.ClientException,
neExceptions.NeutronException,
+ cExceptions.ClientException,
),
):
raise vimconn.VimConnUnexpectedResponse(
elif isinstance(exception, vimconn.VimConnException):
raise exception
else: # ()
- self.logger.error("General Exception " + message_error, exc_info=True)
+ logger = logging.getLogger("ro.vim.openstack")
+ logger.error("General Exception " + message_error, exc_info=True)
- raise vimconn.VimConnConnectionException(
+ raise vimconn.VimConnException(
type(exception).__name__ + ": " + message_error
)
Returns the tenant list of dictionaries: [{'name':'<name>, 'id':'<id>, ...}, ...]
"""
self.logger.debug("Getting tenants from VIM filter: '%s'", str(filter_dict))
-
try:
self._reload_connection()
def new_tenant(self, tenant_name, tenant_description):
"""Adds a new tenant to openstack VIM. Returns the tenant identifier"""
self.logger.debug("Adding a new tenant name: %s", tenant_name)
-
try:
self._reload_connection()
def delete_tenant(self, tenant_id):
"""Delete a tenant from openstack VIM. Returns the old tenant identifier"""
self.logger.debug("Deleting tenant %s from VIM", tenant_id)
-
try:
self._reload_connection()
self.keystone.tenants.delete(tenant_id)
return tenant_id
+
except (
ksExceptions.ConnectionError,
ksExceptions.ClientException,
"dataplane_physical_net"
)
- # if it is non empty list, use the first value. If it is a string use the value directly
+ # if it is non-empty list, use the first value. If it is a string use the value directly
if (
isinstance(provider_physical_network, (tuple, list))
and provider_physical_network
if k_item == "l2gwconn":
self.neutron.delete_l2_gateway_connection(k_id)
+
+ except (neExceptions.ConnectionFailed, ConnectionError) as e2:
+ self.logger.error(
+ "Error deleting l2 gateway connection: {}: {}".format(
+ type(e2).__name__, e2
+ )
+ )
+ self._format_exception(e2)
except Exception as e2:
self.logger.error(
"Error deleting l2 gateway connection: {}: {}".format(
Returns the network list of dictionaries
"""
self.logger.debug("Getting network from VIM filter: '%s'", str(filter_dict))
-
try:
self._reload_connection()
filter_dict_os = filter_dict.copy()
return net
+ @catch_any_exception
def delete_network(self, net_id, created_items=None):
"""
Removes a tenant network from VIM and its associated elements
k_item, _, k_id = k.partition(":")
if k_item == "l2gwconn":
self.neutron.delete_l2_gateway_connection(k_id)
+
+ except (neExceptions.ConnectionFailed, ConnectionError) as e:
+ self.logger.error(
+ "Error deleting l2 gateway connection: {}: {}".format(
+ type(e).__name__, e
+ )
+ )
+ self._format_exception(e)
except Exception as e:
self.logger.error(
"Error deleting l2 gateway connection: {}: {}".format(
for p in ports["ports"]:
try:
self.neutron.delete_port(p["id"])
+
+ except (neExceptions.ConnectionFailed, ConnectionError) as e:
+ self.logger.error("Error deleting port %s: %s", p["id"], str(e))
+ # If there is connection error, it raises.
+ self._format_exception(e)
except Exception as e:
self.logger.error("Error deleting port %s: %s", p["id"], str(e))
self.neutron.delete_network(net_id)
return net_id
- except (
- neExceptions.ConnectionFailed,
- neExceptions.NetworkNotFoundClient,
- neExceptions.NeutronException,
- ksExceptions.ClientException,
- neExceptions.NeutronException,
- ConnectionError,
- ) as e:
- self._format_exception(e)
+ except (neExceptions.NetworkNotFoundClient, neExceptions.NotFound) as e:
+ # If network to be deleted is not found, it does not raise.
+ self.logger.warning(
+ f"Error deleting network: {net_id} is not found, {str(e)}"
+ )
def refresh_nets_status(self, net_list):
"""Get the status of the networks
def get_flavor(self, flavor_id):
"""Obtain flavor details from the VIM. Returns the flavor dict details"""
self.logger.debug("Getting flavor '%s'", flavor_id)
-
try:
self._reload_connection()
flavor = self.nova.flavors.find(id=flavor_id)
- # TODO parse input and translate to VIM format (openmano_schemas.new_vminstance_response_schema)
-
return flavor.to_dict()
+
except (
nvExceptions.NotFound,
nvExceptions.ClientException,
)
except (
nvExceptions.NotFound,
+ nvExceptions.BadRequest,
nvExceptions.ClientException,
ksExceptions.ClientException,
ConnectionError,
flavor_data.get("extended"),
)
+ @catch_any_exception
def new_flavor(self, flavor_data: dict, change_name_if_used: bool = True) -> str:
"""Adds a tenant flavor to openstack VIM.
if change_name_if_used is True, it will change name in case of conflict,
retry = 0
max_retries = 3
name_suffix = 0
+ name = flavor_data["name"]
+ while retry < max_retries:
+ retry += 1
+ try:
+ self._reload_connection()
- try:
- name = flavor_data["name"]
- while retry < max_retries:
- retry += 1
- try:
- self._reload_connection()
+ if change_name_if_used:
+ name = self._change_flavor_name(name, name_suffix, flavor_data)
- if change_name_if_used:
- name = self._change_flavor_name(name, name_suffix, flavor_data)
+ ram, vcpus, extra_specs, extended = self._get_flavor_details(
+ flavor_data
+ )
+ if extended:
+ self._process_extended_config_of_flavor(extended, extra_specs)
- ram, vcpus, extra_specs, extended = self._get_flavor_details(
- flavor_data
- )
- if extended:
- self._process_extended_config_of_flavor(extended, extra_specs)
-
- # Create flavor
-
- new_flavor = self.nova.flavors.create(
- name=name,
- ram=ram,
- vcpus=vcpus,
- disk=flavor_data.get("disk", 0),
- ephemeral=flavor_data.get("ephemeral", 0),
- swap=flavor_data.get("swap", 0),
- is_public=flavor_data.get("is_public", True),
- )
+ # Create flavor
- # Add metadata
- if extra_specs:
- new_flavor.set_keys(extra_specs)
+ new_flavor = self.nova.flavors.create(
+ name=name,
+ ram=ram,
+ vcpus=vcpus,
+ disk=flavor_data.get("disk", 0),
+ ephemeral=flavor_data.get("ephemeral", 0),
+ swap=flavor_data.get("swap", 0),
+ is_public=flavor_data.get("is_public", True),
+ )
- return new_flavor.id
+ # Add metadata
+ if extra_specs:
+ new_flavor.set_keys(extra_specs)
- except nvExceptions.Conflict as e:
- if change_name_if_used and retry < max_retries:
- continue
+ return new_flavor.id
- self._format_exception(e)
+ except nvExceptions.Conflict as e:
+ if change_name_if_used and retry < max_retries:
+ continue
- except (
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- ConnectionError,
- KeyError,
- ) as e:
- self._format_exception(e)
+ self._format_exception(e)
+ @catch_any_exception
def delete_flavor(self, flavor_id):
"""Deletes a tenant flavor from openstack VIM. Returns the old flavor_id"""
try:
self._reload_connection()
self.nova.flavors.delete(flavor_id)
-
return flavor_id
- # except nvExceptions.BadRequest as e:
- except (
- nvExceptions.NotFound,
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- ConnectionError,
- ) as e:
- self._format_exception(e)
+
+ except (nvExceptions.NotFound, nvExceptions.ResourceNotFound) as e:
+ # If flavor is not found, it does not raise.
+ self.logger.warning(
+ f"Error deleting flavor: {flavor_id} is not found, {str(e.message)}"
+ )
def new_image(self, image_dict):
"""
self.glance.images.update(new_image.id, **metadata_to_load)
return new_image.id
- except (
- nvExceptions.Conflict,
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- ) as e:
- self._format_exception(e)
except (
HTTPException,
gl1Exceptions.HTTPException,
"{}: {} for {}".format(type(e).__name__, e, image_dict["location"]),
http_code=vimconn.HTTP_Bad_Request,
)
+ except Exception as e:
+ self._format_exception(e)
+ @catch_any_exception
def delete_image(self, image_id):
"""Deletes a tenant image from openstack VIM. Returns the old id"""
try:
self.glance.images.delete(image_id)
return image_id
- except (
- nvExceptions.NotFound,
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- gl1Exceptions.CommunicationError,
- gl1Exceptions.HTTPNotFound,
- ConnectionError,
- ) as e: # TODO remove
- self._format_exception(e)
+ except gl1Exceptions.NotFound as e:
+ # If image is not found, it does not raise.
+ self.logger.warning(
+ f"Error deleting image: {image_id} is not found, {str(e)}"
+ )
+ @catch_any_exception
def get_image_id_from_path(self, path):
"""Get the image id from image path in the VIM database. Returns the image_id"""
- try:
- self._reload_connection()
- images = self.glance.images.list()
+ self._reload_connection()
+ images = self.glance.images.list()
- for image in images:
- if image.metadata.get("location") == path:
- return image.id
+ for image in images:
+ if image.metadata.get("location") == path:
+ return image.id
- raise vimconn.VimConnNotFoundException(
- "image with location '{}' not found".format(path)
- )
- except (
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- gl1Exceptions.CommunicationError,
- ConnectionError,
- ) as e:
- self._format_exception(e)
+ raise vimconn.VimConnNotFoundException(
+ "image with location '{}' not found".format(path)
+ )
def get_image_list(self, filter_dict={}):
"""Obtain tenant images from VIM
List can be empty
"""
self.logger.debug("Getting image list from VIM filter: '%s'", str(filter_dict))
-
try:
self._reload_connection()
# filter_dict_os = filter_dict.copy()
pass
return filtered_list
+
except (
ksExceptions.ClientException,
nvExceptions.ClientException,
volume_txt += ":keep"
created_items[volume_txt] = True
+ @catch_any_exception
def new_shared_volumes(self, shared_volume_data) -> (str, str):
- try:
- volume = self.cinder.volumes.create(
- size=shared_volume_data["size"],
- name=shared_volume_data["name"],
- volume_type="multiattach",
- )
- return (volume.name, volume.id)
- except (ConnectionError, KeyError) as e:
- self._format_exception(e)
+ volume = self.cinder.volumes.create(
+ size=shared_volume_data["size"],
+ name=shared_volume_data["name"],
+ volume_type="multiattach",
+ )
+ return volume.name, volume.id
def _prepare_shared_volumes(
self,
flavor_id,
str(net_list),
)
+ server = None
+ created_items = {}
+ net_list_vim = []
+ # list of external networks to be connected to instance, later on used to create floating_ip
+ external_network = []
+ # List of ports with port-security disabled
+ no_secured_ports = []
+ block_device_mapping = {}
+ existing_vim_volumes = []
+ server_group_id = None
+ scheduller_hints = {}
try:
- server = None
- created_items = {}
- net_list_vim = []
- # list of external networks to be connected to instance, later on used to create floating_ip
- external_network = []
- # List of ports with port-security disabled
- no_secured_ports = []
- block_device_mapping = {}
- existing_vim_volumes = []
- server_group_id = None
- scheduller_hints = {}
-
# Check the Openstack Connection
self._reload_connection()
"""Returns the VM instance information from VIM"""
return self._find_nova_server(vm_id)
+ @catch_any_exception
def get_vminstance_console(self, vm_id, console_type="vnc"):
"""
Get a console for the virtual machine
suffix: extra text, e.g. the http path and query string
"""
self.logger.debug("Getting VM CONSOLE from VIM")
+ self._reload_connection()
+ server = self.nova.servers.find(id=vm_id)
+
+ if console_type is None or console_type == "novnc":
+ console_dict = server.get_vnc_console("novnc")
+ elif console_type == "xvpvnc":
+ console_dict = server.get_vnc_console(console_type)
+ elif console_type == "rdp-html5":
+ console_dict = server.get_rdp_console(console_type)
+ elif console_type == "spice-html5":
+ console_dict = server.get_spice_console(console_type)
+ else:
+ raise vimconn.VimConnException(
+ "console type '{}' not allowed".format(console_type),
+ http_code=vimconn.HTTP_Bad_Request,
+ )
- try:
- self._reload_connection()
- server = self.nova.servers.find(id=vm_id)
+ console_dict1 = console_dict.get("console")
- if console_type is None or console_type == "novnc":
- console_dict = server.get_vnc_console("novnc")
- elif console_type == "xvpvnc":
- console_dict = server.get_vnc_console(console_type)
- elif console_type == "rdp-html5":
- console_dict = server.get_rdp_console(console_type)
- elif console_type == "spice-html5":
- console_dict = server.get_spice_console(console_type)
- else:
- raise vimconn.VimConnException(
- "console type '{}' not allowed".format(console_type),
- http_code=vimconn.HTTP_Bad_Request,
- )
-
- console_dict1 = console_dict.get("console")
+ if console_dict1:
+ console_url = console_dict1.get("url")
- if console_dict1:
- console_url = console_dict1.get("url")
+ if console_url:
+ # parse console_url
+ protocol_index = console_url.find("//")
+ suffix_index = (
+ console_url[protocol_index + 2 :].find("/") + protocol_index + 2
+ )
+ port_index = (
+ console_url[protocol_index + 2 : suffix_index].find(":")
+ + protocol_index
+ + 2
+ )
- if console_url:
- # parse console_url
- protocol_index = console_url.find("//")
- suffix_index = (
- console_url[protocol_index + 2 :].find("/") + protocol_index + 2
- )
- port_index = (
- console_url[protocol_index + 2 : suffix_index].find(":")
- + protocol_index
- + 2
+ if protocol_index < 0 or port_index < 0 or suffix_index < 0:
+ return (
+ -vimconn.HTTP_Internal_Server_Error,
+ "Unexpected response from VIM",
)
- if protocol_index < 0 or port_index < 0 or suffix_index < 0:
- return (
- -vimconn.HTTP_Internal_Server_Error,
- "Unexpected response from VIM",
- )
-
- console_dict = {
- "protocol": console_url[0:protocol_index],
- "server": console_url[protocol_index + 2 : port_index],
- "port": console_url[port_index:suffix_index],
- "suffix": console_url[suffix_index + 1 :],
- }
- protocol_index += 2
+ console_dict = {
+ "protocol": console_url[0:protocol_index],
+ "server": console_url[protocol_index + 2 : port_index],
+ "port": console_url[port_index:suffix_index],
+ "suffix": console_url[suffix_index + 1 :],
+ }
+ protocol_index += 2
- return console_dict
- raise vimconn.VimConnUnexpectedResponse("Unexpected response from VIM")
- except (
- nvExceptions.NotFound,
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- nvExceptions.BadRequest,
- ConnectionError,
- ) as e:
- self._format_exception(e)
+ return console_dict
+ raise vimconn.VimConnUnexpectedResponse("Unexpected response from VIM")
def _delete_ports_by_id_wth_neutron(self, k_id: str) -> None:
"""Neutron delete ports by id.
try:
self.neutron.delete_port(k_id)
+ except (neExceptions.ConnectionFailed, ConnectionError) as e:
+ self.logger.error("Error deleting port: {}: {}".format(type(e).__name__, e))
+ # If there is connection error, raise.
+ self._format_exception(e)
except Exception as e:
self.logger.error("Error deleting port: {}: {}".format(type(e).__name__, e))
"""
try:
if k_id in volumes_to_hold:
- return
+ return False
if self.cinder.volumes.get(k_id).status != "available":
return True
self.cinder.volumes.delete(k_id)
created_items[k] = None
+ except (cExceptions.ConnectionError, ConnectionError) as e:
+ self.logger.error(
+ "Error deleting volume: {}: {}".format(type(e).__name__, e)
+ )
+ self._format_exception(e)
except Exception as e:
self.logger.error(
"Error deleting volume: {}: {}".format(type(e).__name__, e)
self.neutron.delete_floatingip(k_id)
created_items[k] = None
+ except (neExceptions.ConnectionFailed, ConnectionError) as e:
+ self.logger.error(
+ "Error deleting floating ip: {}: {}".format(type(e).__name__, e)
+ )
+ self._format_exception(e)
except Exception as e:
self.logger.error(
"Error deleting floating ip: {}: {}".format(type(e).__name__, e)
if k_item == "port":
self._delete_ports_by_id_wth_neutron(k_id)
+ except (neExceptions.ConnectionFailed, ConnectionError) as e:
+ self.logger.error(
+ "Error deleting port: {}: {}".format(type(e).__name__, e)
+ )
+ self._format_exception(e)
except Exception as e:
self.logger.error(
"Error deleting port: {}: {}".format(type(e).__name__, e)
elif k_item == "floating_ip":
self._delete_floating_ip_by_id(k, k_id, created_items)
+ except (
+ cExceptions.ConnectionError,
+ neExceptions.ConnectionFailed,
+ ConnectionError,
+ AttributeError,
+ TypeError,
+ ) as e:
+ self.logger.error("Error deleting {}: {}".format(k, e))
+ self._format_exception(e)
+
except Exception as e:
self.logger.error("Error deleting {}: {}".format(k, e))
if len(key.split(":")) == 2
}
+ @catch_any_exception
def delete_vminstance(
self, vm_id: str, created_items: dict = None, volumes_to_hold: list = None
) -> None:
if keep_waiting:
time.sleep(1)
elapsed_time += 1
-
- except (
- nvExceptions.NotFound,
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- ConnectionError,
- ) as e:
- self._format_exception(e)
+ except (nvExceptions.NotFound, nvExceptions.ResourceNotFound) as e:
+ # If VM does not exist, it does not raise
+ self.logger.warning(f"Error deleting VM: {vm_id} is not found, {str(e)}")
def refresh_vms_status(self, vm_list):
"""Get the status of the virtual machines and their interfaces/ports
self.logger.debug(
"refresh_vms status: Getting tenant VM instance information from VIM"
)
-
for vm_id in vm_list:
vm = {}
return vm_dict
+ @catch_any_exception
def action_vminstance(self, vm_id, action_dict, created_items={}):
"""Send and action over a VM instance from VIM
Returns None or the console dict if the action was successfully sent to the VIM
"""
self.logger.debug("Action over VM '%s': %s", vm_id, str(action_dict))
-
- try:
- self._reload_connection()
- server = self.nova.servers.find(id=vm_id)
-
- if "start" in action_dict:
- if action_dict["start"] == "rebuild":
- server.rebuild()
- else:
- if server.status == "PAUSED":
- server.unpause()
- elif server.status == "SUSPENDED":
- server.resume()
- elif server.status == "SHUTOFF":
- server.start()
- else:
- self.logger.debug(
- "ERROR : Instance is not in SHUTOFF/PAUSE/SUSPEND state"
- )
- raise vimconn.VimConnException(
- "Cannot 'start' instance while it is in active state",
- http_code=vimconn.HTTP_Bad_Request,
- )
-
- elif "pause" in action_dict:
- server.pause()
- elif "resume" in action_dict:
- server.resume()
- elif "shutoff" in action_dict or "shutdown" in action_dict:
- self.logger.debug("server status %s", server.status)
- if server.status == "ACTIVE":
- server.stop()
+ self._reload_connection()
+ server = self.nova.servers.find(id=vm_id)
+ if "start" in action_dict:
+ if action_dict["start"] == "rebuild":
+ server.rebuild()
+ else:
+ if server.status == "PAUSED":
+ server.unpause()
+ elif server.status == "SUSPENDED":
+ server.resume()
+ elif server.status == "SHUTOFF":
+ server.start()
else:
- self.logger.debug("ERROR: VM is not in Active state")
- raise vimconn.VimConnException(
- "VM is not in active state, stop operation is not allowed",
- http_code=vimconn.HTTP_Bad_Request,
+ self.logger.debug(
+ "ERROR : Instance is not in SHUTOFF/PAUSE/SUSPEND state"
)
- elif "forceOff" in action_dict:
- server.stop() # TODO
- elif "terminate" in action_dict:
- server.delete()
- elif "createImage" in action_dict:
- server.create_image()
- # "path":path_schema,
- # "description":description_schema,
- # "name":name_schema,
- # "metadata":metadata_schema,
- # "imageRef": id_schema,
- # "disk": {"oneOf":[{"type": "null"}, {"type":"string"}] },
- elif "rebuild" in action_dict:
- server.rebuild(server.image["id"])
- elif "reboot" in action_dict:
- server.reboot() # reboot_type="SOFT"
- elif "console" in action_dict:
- console_type = action_dict["console"]
-
- if console_type is None or console_type == "novnc":
- console_dict = server.get_vnc_console("novnc")
- elif console_type == "xvpvnc":
- console_dict = server.get_vnc_console(console_type)
- elif console_type == "rdp-html5":
- console_dict = server.get_rdp_console(console_type)
- elif console_type == "spice-html5":
- console_dict = server.get_spice_console(console_type)
- else:
raise vimconn.VimConnException(
- "console type '{}' not allowed".format(console_type),
+ "Cannot 'start' instance while it is in active state",
http_code=vimconn.HTTP_Bad_Request,
)
+ elif "pause" in action_dict:
+ server.pause()
+ elif "resume" in action_dict:
+ server.resume()
+ elif "shutoff" in action_dict or "shutdown" in action_dict:
+ self.logger.debug("server status %s", server.status)
+ if server.status == "ACTIVE":
+ server.stop()
+ else:
+ self.logger.debug("ERROR: VM is not in Active state")
+ raise vimconn.VimConnException(
+ "VM is not in active state, stop operation is not allowed",
+ http_code=vimconn.HTTP_Bad_Request,
+ )
+ elif "forceOff" in action_dict:
+ server.stop() # TODO
+ elif "terminate" in action_dict:
+ server.delete()
+ elif "createImage" in action_dict:
+ server.create_image()
+ # "path":path_schema,
+ # "description":description_schema,
+ # "name":name_schema,
+ # "metadata":metadata_schema,
+ # "imageRef": id_schema,
+ # "disk": {"oneOf":[{"type": "null"}, {"type":"string"}] },
+ elif "rebuild" in action_dict:
+ server.rebuild(server.image["id"])
+ elif "reboot" in action_dict:
+ server.reboot() # reboot_type="SOFT"
+ elif "console" in action_dict:
+ console_type = action_dict["console"]
- try:
- console_url = console_dict["console"]["url"]
- # parse console_url
- protocol_index = console_url.find("//")
- suffix_index = (
- console_url[protocol_index + 2 :].find("/") + protocol_index + 2
- )
- port_index = (
- console_url[protocol_index + 2 : suffix_index].find(":")
- + protocol_index
- + 2
- )
-
- if protocol_index < 0 or port_index < 0 or suffix_index < 0:
- raise vimconn.VimConnException(
- "Unexpected response from VIM " + str(console_dict)
- )
+ if console_type is None or console_type == "novnc":
+ console_dict = server.get_vnc_console("novnc")
+ elif console_type == "xvpvnc":
+ console_dict = server.get_vnc_console(console_type)
+ elif console_type == "rdp-html5":
+ console_dict = server.get_rdp_console(console_type)
+ elif console_type == "spice-html5":
+ console_dict = server.get_spice_console(console_type)
+ else:
+ raise vimconn.VimConnException(
+ "console type '{}' not allowed".format(console_type),
+ http_code=vimconn.HTTP_Bad_Request,
+ )
- console_dict2 = {
- "protocol": console_url[0:protocol_index],
- "server": console_url[protocol_index + 2 : port_index],
- "port": int(console_url[port_index + 1 : suffix_index]),
- "suffix": console_url[suffix_index + 1 :],
- }
+ try:
+ console_url = console_dict["console"]["url"]
+ # parse console_url
+ protocol_index = console_url.find("//")
+ suffix_index = (
+ console_url[protocol_index + 2 :].find("/") + protocol_index + 2
+ )
+ port_index = (
+ console_url[protocol_index + 2 : suffix_index].find(":")
+ + protocol_index
+ + 2
+ )
- return console_dict2
- except Exception:
+ if protocol_index < 0 or port_index < 0 or suffix_index < 0:
raise vimconn.VimConnException(
"Unexpected response from VIM " + str(console_dict)
)
- return None
- except (
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- nvExceptions.NotFound,
- ConnectionError,
- ) as e:
- self._format_exception(e)
- # TODO insert exception vimconn.HTTP_Unauthorized
+ console_dict2 = {
+ "protocol": console_url[0:protocol_index],
+ "server": console_url[protocol_index + 2 : port_index],
+ "port": int(console_url[port_index + 1 : suffix_index]),
+ "suffix": console_url[suffix_index + 1 :],
+ }
+
+ return console_dict2
+ except Exception:
+ raise vimconn.VimConnException(
+ "Unexpected response from VIM " + str(console_dict)
+ )
+
+ return None
# ###### VIO Specific Changes #########
def _generate_vlanID(self):
return error_value, error_text
+ @catch_any_exception
def new_affinity_group(self, affinity_group_data):
"""Adds a server group to VIM
affinity_group_data contains a dictionary with information, keys:
scope: Only nfvi-node allowed
Returns the server group identifier"""
self.logger.debug("Adding Server Group '%s'", str(affinity_group_data))
+ name = affinity_group_data["name"]
+ policy = affinity_group_data["type"]
+ self._reload_connection()
+ new_server_group = self.nova.server_groups.create(name, policy)
+ return new_server_group.id
- try:
- name = affinity_group_data["name"]
- policy = affinity_group_data["type"]
-
- self._reload_connection()
- new_server_group = self.nova.server_groups.create(name, policy)
-
- return new_server_group.id
- except (
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- ConnectionError,
- KeyError,
- ) as e:
- self._format_exception(e)
-
+ @catch_any_exception
def get_affinity_group(self, affinity_group_id):
"""Obtain server group details from the VIM. Returns the server group detais as a dict"""
self.logger.debug("Getting flavor '%s'", affinity_group_id)
- try:
- self._reload_connection()
- server_group = self.nova.server_groups.find(id=affinity_group_id)
-
- return server_group.to_dict()
- except (
- nvExceptions.NotFound,
- nvExceptions.ClientException,
- ksExceptions.ClientException,
- ConnectionError,
- ) as e:
- self._format_exception(e)
+ self._reload_connection()
+ server_group = self.nova.server_groups.find(id=affinity_group_id)
+ return server_group.to_dict()
+ @catch_any_exception
def delete_affinity_group(self, affinity_group_id):
"""Deletes a server group from the VIM. Returns the old affinity_group_id"""
self.logger.debug("Getting server group '%s'", affinity_group_id)
- try:
- self._reload_connection()
- self.nova.server_groups.delete(affinity_group_id)
-
- return affinity_group_id
- except (
- nvExceptions.NotFound,
- ksExceptions.ClientException,
- nvExceptions.ClientException,
- ConnectionError,
- ) as e:
- self._format_exception(e)
+ self._reload_connection()
+ self.nova.server_groups.delete(affinity_group_id)
+ return affinity_group_id
+ @catch_any_exception
def get_vdu_state(self, vm_id, host_is_required=False) -> list:
"""Getting the state of a VDU.
Args:
"""
self.logger.debug("Getting the status of VM")
self.logger.debug("VIM VM ID %s", vm_id)
- try:
- self._reload_connection()
- server_dict = self._find_nova_server(vm_id)
- srv_attr = "OS-EXT-SRV-ATTR:host"
- host_info = (
- server_dict[srv_attr] if host_is_required else server_dict.get(srv_attr)
- )
- vdu_data = [
- server_dict["status"],
- server_dict["flavor"]["id"],
- host_info,
- server_dict["OS-EXT-AZ:availability_zone"],
- ]
- self.logger.debug("vdu_data %s", vdu_data)
- return vdu_data
-
- except Exception as e:
- self._format_exception(e)
+ self._reload_connection()
+ server_dict = self._find_nova_server(vm_id)
+ srv_attr = "OS-EXT-SRV-ATTR:host"
+ host_info = (
+ server_dict[srv_attr] if host_is_required else server_dict.get(srv_attr)
+ )
+ vdu_data = [
+ server_dict["status"],
+ server_dict["flavor"]["id"],
+ host_info,
+ server_dict["OS-EXT-AZ:availability_zone"],
+ ]
+ self.logger.debug("vdu_data %s", vdu_data)
+ return vdu_data
def check_compute_availability(self, host, server_flavor_details):
self._reload_connection()
az_check["zone_check"] = True
return az_check
+ @catch_any_exception
def migrate_instance(self, vm_id, compute_host=None):
"""
Migrate a vdu
server_flavor_id = instance_state[1]
server_hypervisor_name = instance_state[2]
server_availability_zone = instance_state[3]
- try:
- server_flavor = self.nova.flavors.find(id=server_flavor_id).to_dict()
- server_flavor_details = [
- server_flavor["ram"],
- server_flavor["disk"],
- server_flavor["vcpus"],
- ]
- if compute_host == server_hypervisor_name:
- raise vimconn.VimConnException(
- "Unable to migrate instance '{}' to the same host '{}'".format(
- vm_id, compute_host
- ),
- http_code=vimconn.HTTP_Bad_Request,
- )
- az_status = self.check_availability_zone(
- server_availability_zone,
- server_flavor_details,
- server_hypervisor_name,
- compute_host,
+ server_flavor = self.nova.flavors.find(id=server_flavor_id).to_dict()
+ server_flavor_details = [
+ server_flavor["ram"],
+ server_flavor["disk"],
+ server_flavor["vcpus"],
+ ]
+ if compute_host == server_hypervisor_name:
+ raise vimconn.VimConnException(
+ "Unable to migrate instance '{}' to the same host '{}'".format(
+ vm_id, compute_host
+ ),
+ http_code=vimconn.HTTP_Bad_Request,
)
- availability_zone_check = az_status["zone_check"]
- available_compute_id = az_status.get("compute_availability")
+ az_status = self.check_availability_zone(
+ server_availability_zone,
+ server_flavor_details,
+ server_hypervisor_name,
+ compute_host,
+ )
+ availability_zone_check = az_status["zone_check"]
+ available_compute_id = az_status.get("compute_availability")
- if availability_zone_check is False:
- raise vimconn.VimConnException(
- "Unable to migrate instance '{}' to a different availability zone".format(
- vm_id
- ),
- http_code=vimconn.HTTP_Bad_Request,
- )
- if available_compute_id is not None:
- # disk_over_commit parameter for live_migrate method is not valid for Nova API version >= 2.25
- self.nova.servers.live_migrate(
- server=vm_id,
- host=available_compute_id,
- block_migration=True,
- )
- state = "MIGRATING"
- changed_compute_host = ""
- if state == "MIGRATING":
- vm_state = self.__wait_for_vm(vm_id, "ACTIVE")
- changed_compute_host = self.get_vdu_state(
- vm_id, host_is_required=True
- )[2]
- if vm_state and changed_compute_host == available_compute_id:
- self.logger.debug(
- "Instance '{}' migrated to the new compute host '{}'".format(
- vm_id, changed_compute_host
- )
- )
- return state, available_compute_id
- else:
- raise vimconn.VimConnException(
- "Migration Failed. Instance '{}' not moved to the new host {}".format(
- vm_id, available_compute_id
- ),
- http_code=vimconn.HTTP_Bad_Request,
+ if availability_zone_check is False:
+ raise vimconn.VimConnException(
+ "Unable to migrate instance '{}' to a different availability zone".format(
+ vm_id
+ ),
+ http_code=vimconn.HTTP_Bad_Request,
+ )
+ if available_compute_id is not None:
+ # disk_over_commit parameter for live_migrate method is not valid for Nova API version >= 2.25
+ self.nova.servers.live_migrate(
+ server=vm_id,
+ host=available_compute_id,
+ block_migration=True,
+ )
+ state = "MIGRATING"
+ changed_compute_host = ""
+ if state == "MIGRATING":
+ vm_state = self.__wait_for_vm(vm_id, "ACTIVE")
+ changed_compute_host = self.get_vdu_state(vm_id, host_is_required=True)[
+ 2
+ ]
+ if vm_state and changed_compute_host == available_compute_id:
+ self.logger.debug(
+ "Instance '{}' migrated to the new compute host '{}'".format(
+ vm_id, changed_compute_host
)
+ )
+ return state, available_compute_id
else:
raise vimconn.VimConnException(
- "Compute '{}' not available or does not have enough resources to migrate the instance".format(
- available_compute_id
+ "Migration Failed. Instance '{}' not moved to the new host {}".format(
+ vm_id, available_compute_id
),
http_code=vimconn.HTTP_Bad_Request,
)
- except (
- nvExceptions.BadRequest,
- nvExceptions.ClientException,
- nvExceptions.NotFound,
- ) as e:
- self._format_exception(e)
+ else:
+ raise vimconn.VimConnException(
+ "Compute '{}' not available or does not have enough resources to migrate the instance".format(
+ available_compute_id
+ ),
+ http_code=vimconn.HTTP_Bad_Request,
+ )
+ @catch_any_exception
def resize_instance(self, vm_id, new_flavor_id):
"""
For resizing the vm based on the given
instance_status, old_flavor_id, compute_host, az = self.get_vdu_state(vm_id)
old_flavor_disk = self.nova.flavors.find(id=old_flavor_id).to_dict()["disk"]
new_flavor_disk = self.nova.flavors.find(id=new_flavor_id).to_dict()["disk"]
- try:
- if instance_status == "ACTIVE" or instance_status == "SHUTOFF":
- if old_flavor_disk > new_flavor_disk:
+ if instance_status == "ACTIVE" or instance_status == "SHUTOFF":
+ if old_flavor_disk > new_flavor_disk:
+ raise nvExceptions.BadRequest(
+ 400,
+ message="Server disk resize failed. Resize to lower disk flavor is not allowed",
+ )
+ else:
+ self.nova.servers.resize(server=vm_id, flavor=new_flavor_id)
+ vm_state = self.__wait_for_vm(vm_id, "VERIFY_RESIZE")
+ if vm_state:
+ instance_resized_status = self.confirm_resize(vm_id)
+ return instance_resized_status
+ else:
raise nvExceptions.BadRequest(
- 400,
- message="Server disk resize failed. Resize to lower disk flavor is not allowed",
+ 409,
+ message="Cannot 'resize' vm_state is in ERROR",
)
- else:
- self.nova.servers.resize(server=vm_id, flavor=new_flavor_id)
- vm_state = self.__wait_for_vm(vm_id, "VERIFY_RESIZE")
- if vm_state:
- instance_resized_status = self.confirm_resize(vm_id)
- return instance_resized_status
- else:
- raise nvExceptions.BadRequest(
- 409,
- message="Cannot 'resize' vm_state is in ERROR",
- )
- else:
- self.logger.debug("ERROR : Instance is not in ACTIVE or SHUTOFF state")
- raise nvExceptions.BadRequest(
- 409,
- message="Cannot 'resize' instance while it is in vm_state resized",
- )
- except (
- nvExceptions.BadRequest,
- nvExceptions.ClientException,
- nvExceptions.NotFound,
- ) as e:
- self._format_exception(e)
+ else:
+ self.logger.debug("ERROR : Instance is not in ACTIVE or SHUTOFF state")
+ raise nvExceptions.BadRequest(
+ 409,
+ message="Cannot 'resize' instance while it is in vm_state resized",
+ )
def confirm_resize(self, vm_id):
"""
self.logger.warning(str(e.message))
all_ports = self.neutron.list_ports()
return all_servers, all_ports
- except (
- vimconn.VimConnException,
- vimconn.VimConnNotFoundException,
- vimconn.VimConnConnectionException,
- ) as e:
+ except Exception as e:
raise vimconn.VimConnException(
f"Exception in monitoring while getting VMs and ports status: {str(e)}"
)