Bug 2316: Fix for Unable to do vertical scaling when VM is in Shutdown state
[osm/RO.git] / osm_ro / wim / wan_link_actions.py
diff --git a/osm_ro/wim/wan_link_actions.py b/osm_ro/wim/wan_link_actions.py
deleted file mode 100644 (file)
index 1993ae7..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-# -*- coding: utf-8 -*-
-##
-# Copyright 2018 University of Bristol - High Performance Networks Research
-# Group
-# All Rights Reserved.
-#
-# Contributors: Anderson Bravalheri, Dimitrios Gkounis, Abubakar Siddique
-# Muqaddas, Navdeep Uniyal, Reza Nejabati and Dimitra Simeonidou
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact with: <highperformance-networks@bristol.ac.uk>
-#
-# Neither the name of the University of Bristol nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# This work has been performed in the context of DCMS UK 5G Testbeds
-# & Trials Programme and in the framework of the Metro-Haul project -
-# funded by the European Commission under Grant number 761727 through the
-# Horizon 2020 and 5G-PPP programmes.
-##
-# pylint: disable=E1101,E0203,W0201
-import json
-from time import time
-
-from ..utils import filter_dict_keys as filter_keys
-from ..utils import merge_dicts, remove_none_items, safe_get, truncate
-from .actions import CreateAction, DeleteAction, FindAction
-from .errors import (
-    InconsistentState,
-    MultipleRecordsFound,
-    NoRecordFound,
-)
-from wimconn import WimConnectorError
-
-INSTANCE_NET_STATUS_ERROR = ('DOWN', 'ERROR', 'VIM_ERROR',
-                             'DELETED', 'SCHEDULED_DELETION')
-INSTANCE_NET_STATUS_PENDING = ('BUILD', 'INACTIVE', 'SCHEDULED_CREATION')
-INSTANCE_VM_STATUS_ERROR = ('ERROR', 'VIM_ERROR',
-                            'DELETED', 'SCHEDULED_DELETION')
-
-
-class RefreshMixin(object):
-    def refresh(self, connector, persistence):
-        """Ask the external WAN Infrastructure Manager system for updates on
-        the status of the task.
-
-        Arguments:
-            connector: object with API for accessing the WAN
-                Infrastructure Manager system
-            persistence: abstraction layer for the database
-        """
-        fields = ('wim_status', 'wim_info', 'error_msg')
-        result = dict.fromkeys(fields)
-
-        try:
-            result.update(
-                connector
-                .get_connectivity_service_status(self.wim_internal_id))
-        except WimConnectorError as ex:
-            self.logger.exception(ex)
-            result.update(wim_status='WIM_ERROR', error_msg=truncate(ex))
-
-        result = filter_keys(result, fields)
-
-        action_changes = remove_none_items({
-            'extra': merge_dicts(self.extra, result),
-            'status': 'BUILD' if result['wim_status'] == 'BUILD' else None,
-            'error_msg': result['error_msg'],
-            'modified_at': time()})
-        link_changes = merge_dicts(result, status=result.pop('wim_status'))
-        # ^  Rename field: wim_status => status
-
-        persistence.update_wan_link(self.item_id,
-                                    remove_none_items(link_changes))
-
-        self.save(persistence, **action_changes)
-
-        return result
-
-
-class WanLinkCreate(RefreshMixin, CreateAction):
-    def fail(self, persistence, reason, status='FAILED'):
-        changes = {'status': 'ERROR', 'error_msg': truncate(reason)}
-        persistence.update_wan_link(self.item_id, changes)
-        return super(WanLinkCreate, self).fail(persistence, reason, status)
-
-    def process(self, connector, persistence, ovim):
-        """Process the current task.
-        First we check if all the dependencies are ready,
-        then we call ``execute`` to actually execute the action.
-
-        Arguments:
-            connector: object with API for accessing the WAN
-                Infrastructure Manager system
-            persistence: abstraction layer for the database
-            ovim: instance of openvim, abstraction layer that enable
-                SDN-related operations
-        """
-        wan_link = persistence.get_by_uuid('instance_wim_nets', self.item_id)
-
-        # First we check if all the dependencies are solved
-        instance_nets = persistence.get_instance_nets(
-            wan_link['instance_scenario_id'], wan_link['sce_net_id'])
-
-        try:
-            dependency_statuses = [n['status'] for n in instance_nets]
-        except KeyError:
-            self.logger.debug('`status` not found in\n\n%s\n\n',
-                              json.dumps(instance_nets, indent=4))
-        errored = [instance_nets[i]
-                   for i, status in enumerate(dependency_statuses)
-                   if status in INSTANCE_NET_STATUS_ERROR]
-        if errored:
-            return self.fail(
-                persistence,
-                'Impossible to stablish WAN connectivity due to an issue '
-                'with the local networks:\n\t' +
-                '\n\t'.join('{uuid}: {status}'.format(**n) for n in errored))
-
-        pending = [instance_nets[i]
-                   for i, status in enumerate(dependency_statuses)
-                   if status in INSTANCE_NET_STATUS_PENDING]
-        if pending:
-            return self.defer(
-                persistence,
-                'Still waiting for the local networks to be active:\n\t' +
-                '\n\t'.join('{uuid}: {status}'.format(**n) for n in pending))
-
-        return self.execute(connector, persistence, ovim, instance_nets)
-
-    def get_endpoint(self, persistence, ovim, instance_net):
-        """Retrieve the endpoint (information about the connection PoP <> WAN
-        """
-        wim_account = persistence.get_wim_account_by(uuid=self.wim_account_id)
-
-        # TODO: make more generic to support networks that are not created with
-        # the SDN assist. This method should have a consistent way of getting
-        # the endpoint for all different types of networks used in the VIM
-        # (provider networks, SDN assist, overlay networks, ...)
-        if instance_net.get('sdn_net_id'):
-            return self.get_endpoint_sdn(
-                persistence, ovim, instance_net, wim_account['wim_id'])
-        else:
-            raise InconsistentState(
-                'The field `instance_nets.sdn_net_id` was expected to be '
-                'found in the database for the record %s after the network '
-                'become active, but it is still NULL', instance_net['uuid'])
-
-    def get_endpoint_sdn(self, persistence, ovim, instance_net, wim_id):
-        criteria = {'net_id': instance_net['sdn_net_id']}
-        local_port_mapping = ovim.get_ports(filter=criteria)
-
-        if len(local_port_mapping) > 1:
-            raise MultipleRecordsFound(criteria, 'ovim.ports')
-        local_port_mapping = local_port_mapping[0]
-
-        criteria = {
-            'wim_id': wim_id,
-            'pop_switch_dpid': local_port_mapping['switch_dpid'],
-            'pop_switch_port': local_port_mapping['switch_port'],
-            'datacenter_id': instance_net['datacenter_id']}
-
-        wan_port_mapping = persistence.query_one(
-            FROM='wim_port_mappings',
-            WHERE=criteria)
-
-        if local_port_mapping.get('vlan'):
-            wan_port_mapping['wan_service_mapping_info']['vlan'] = (
-                local_port_mapping['vlan'])
-
-        return wan_port_mapping
-
-    @staticmethod
-    def _derive_connection_point(endpoint):
-        point = {'service_endpoint_id': endpoint['wan_service_endpoint_id']}
-        # TODO: Cover other scenarios, e.g. VXLAN.
-        info = endpoint.get('wan_service_mapping_info', {})
-        if 'vlan' in info:
-            point['service_endpoint_encapsulation_type'] = 'dot1q'
-            point['service_endpoint_encapsulation_info'] = {
-                'vlan': info['vlan']
-            }
-        else:
-            point['service_endpoint_encapsulation_type'] = 'none'
-        return point
-
-    @staticmethod
-    def _derive_service_type(connection_points):
-        # TODO: add multipoint and L3 connectivity.
-        if len(connection_points) == 2:
-            return 'ELINE'
-        else:
-            raise NotImplementedError('Multipoint connectivity is not '
-                                      'supported yet.')
-
-    def _update_persistent_data(self, persistence, service_uuid,
-                                endpoints, conn_info):
-        """Store plugin/connector specific information in the database"""
-        persistence.update_wan_link(self.item_id, {
-            'wim_internal_id': service_uuid,
-            'wim_info': {'conn_info': conn_info},
-            'status': 'BUILD'})
-
-    def execute(self, connector, persistence, ovim, instance_nets):
-        """Actually execute the action, since now we are sure all the
-        dependencies are solved
-        """
-        try:
-            endpoints = [self.get_endpoint(persistence, ovim, net)
-                         for net in instance_nets]
-            connection_points = [self._derive_connection_point(e)
-                                 for e in endpoints]
-
-            uuid, info = connector.create_connectivity_service(
-                self._derive_service_type(connection_points),
-                connection_points
-                # TODO: other properties, e.g. bandwidth
-            )
-        except (WimConnectorError, InconsistentState) as ex:
-            self.logger.exception(ex)
-            return self.fail(
-                persistence,
-                'Impossible to stablish WAN connectivity.\n\t{}'.format(ex))
-
-        self.logger.debug('WAN connectivity established %s\n%s\n',
-                          uuid, json.dumps(info, indent=4))
-        self.wim_internal_id = uuid
-        self._update_persistent_data(persistence, uuid, endpoints, info)
-        self.succeed(persistence)
-        return uuid
-
-
-class WanLinkDelete(DeleteAction):
-    def succeed(self, persistence):
-        try:
-            persistence.update_wan_link(self.item_id, {'status': 'DELETED'})
-        except NoRecordFound:
-            self.logger.debug('%s(%s) record already deleted',
-                              self.item, self.item_id)
-
-        return super(WanLinkDelete, self).succeed(persistence)
-
-    def get_wan_link(self, persistence):
-        """Retrieve information about the wan_link
-
-        It might be cached, or arrive from the database
-        """
-        if self.extra.get('wan_link'):
-            # First try a cached version of the data
-            return self.extra['wan_link']
-
-        return persistence.get_by_uuid(
-            'instance_wim_nets', self.item_id)
-
-    def process(self, connector, persistence, ovim):
-        """Delete a WAN link previously created"""
-        wan_link = self.get_wan_link(persistence)
-        if 'ERROR' in (wan_link.get('status') or ''):
-            return self.fail(
-                persistence,
-                'Impossible to delete WAN connectivity, '
-                'it was never successfully established:'
-                '\n\t{}'.format(wan_link['error_msg']))
-
-        internal_id = wan_link.get('wim_internal_id') or self.internal_id
-
-        if not internal_id:
-            self.logger.debug('No wim_internal_id found in\n%s\n%s\n'
-                              'Assuming no network was created yet, '
-                              'so no network have to be deleted.',
-                              json.dumps(wan_link, indent=4),
-                              json.dumps(self.as_dict(), indent=4))
-            return self.succeed(persistence)
-
-        try:
-            id = self.wim_internal_id
-            conn_info = safe_get(wan_link, 'wim_info.conn_info')
-            self.logger.debug('Connection Service %s (wan_link: %s):\n%s\n',
-                              id, wan_link['uuid'],
-                              json.dumps(conn_info, indent=4))
-            result = connector.delete_connectivity_service(id, conn_info)
-        except (WimConnectorError, InconsistentState) as ex:
-            self.logger.exception(ex)
-            return self.fail(
-                persistence,
-                'Impossible to delete WAN connectivity.\n\t{}'.format(ex))
-
-        self.logger.debug('WAN connectivity removed %s', result)
-        self.succeed(persistence)
-
-        return result
-
-
-class WanLinkFind(RefreshMixin, FindAction):
-    pass
-
-
-ACTIONS = {
-    'CREATE': WanLinkCreate,
-    'DELETE': WanLinkDelete,
-    'FIND': WanLinkFind,
-}