nfv/nfv/nfv-vim/nfv_vim/objects/_guest_services.py

420 lines
15 KiB
Python
Executable File

#
# Copyright (c) 2015-2016 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import six
from nfv_common import debug
from nfv_common.helpers import Constant
from nfv_common.helpers import Singleton
from nfv_vim.objects._object import ObjectData
from nfv_vim import nfvi
DLOG = debug.debug_get_logger('nfv_vim.objects.guest_services')
@six.add_metaclass(Singleton)
class GuestServiceNames(object):
"""
Guest Services Name Constants
"""
HEARTBEAT = Constant('heartbeat')
# Guest Services Constant Instantiation
GUEST_SERVICE_NAME = GuestServiceNames()
class GuestServices(ObjectData):
"""
Guest Services Object
"""
SERVICE_NOT_CONFIGURED = "not-configured"
SERVICE_CONFIGURED = "configured"
SERVICE_ENABLING = "enabling"
SERVICE_DISABLING = "disabling"
SERVICE_ENABLED = "enabled"
SERVICE_DISABLED = "disabled"
SERVICE_DELETING = "deleting"
def __init__(self, services=None, nfvi_guest_services=None):
super(GuestServices, self).__init__('1.0.0')
if services is None:
self._services = dict()
else:
self._services = services
if nfvi_guest_services is not None:
if 0 == len(nfvi_guest_services):
self._nfvi_guest_services = None
else:
self._nfvi_guest_services = nfvi_guest_services
else:
self._nfvi_guest_services = None
@staticmethod
def _convert_nfvi_service_name(nfvi_service_name):
"""
Returns the service name given the nfvi service name
"""
if nfvi.objects.v1.GUEST_SERVICE_NAME.HEARTBEAT == nfvi_service_name:
return GUEST_SERVICE_NAME.HEARTBEAT
return None
@staticmethod
def _convert_nfvi_service_state(nfvi_service_admin_state,
nfvi_service_oper_state):
"""
Returns the service state given the nfvi service state
"""
if nfvi.objects.v1.GUEST_SERVICE_ADMIN_STATE.LOCKED \
== nfvi_service_admin_state:
return GuestServices.SERVICE_DISABLED
else:
if nfvi.objects.v1.GUEST_SERVICE_OPER_STATE.ENABLED \
== nfvi_service_oper_state:
return GuestServices.SERVICE_ENABLED
else:
return GuestServices.SERVICE_ENABLING
@staticmethod
def _get_nfvi_service_name(service_name):
"""
Returns the nfvi service name
"""
if GUEST_SERVICE_NAME.HEARTBEAT == service_name:
return nfvi.objects.v1.GUEST_SERVICE_NAME.HEARTBEAT
return None
@staticmethod
def _get_nfvi_service_admin_state(service_state):
"""
Returns the nfvi service state
"""
if GuestServices.SERVICE_NOT_CONFIGURED == service_state:
return nfvi.objects.v1.GUEST_SERVICE_ADMIN_STATE.LOCKED
elif GuestServices.SERVICE_CONFIGURED == service_state:
return nfvi.objects.v1.GUEST_SERVICE_ADMIN_STATE.LOCKED
elif GuestServices.SERVICE_ENABLING == service_state:
return nfvi.objects.v1.GUEST_SERVICE_ADMIN_STATE.UNLOCKED
elif GuestServices.SERVICE_DISABLING == service_state:
return nfvi.objects.v1.GUEST_SERVICE_ADMIN_STATE.LOCKED
elif GuestServices.SERVICE_ENABLED == service_state:
return nfvi.objects.v1.GUEST_SERVICE_ADMIN_STATE.UNLOCKED
elif GuestServices.SERVICE_DISABLED == service_state:
return nfvi.objects.v1.GUEST_SERVICE_ADMIN_STATE.LOCKED
else:
return nfvi.objects.v1.GUEST_SERVICE_ADMIN_STATE.LOCKED
@property
def services(self):
"""
Returns a list of services
"""
return list(self._services)
@property
def state(self):
"""
Returns the overall state of the guest services
"""
def update_overall_state(current_state, state):
"""
Returns the overall_state updated if needed
"""
if current_state is None:
return state
if GuestServices.SERVICE_DELETING == current_state:
return GuestServices.SERVICE_DELETING
if GuestServices.SERVICE_DELETING != current_state:
if GuestServices.SERVICE_NOT_CONFIGURED == state:
return GuestServices.SERVICE_NOT_CONFIGURED
if GuestServices.SERVICE_DELETING != current_state \
and GuestServices.SERVICE_NOT_CONFIGURED != current_state:
if GuestServices.SERVICE_CONFIGURED == state:
return GuestServices.SERVICE_CONFIGURED
if GuestServices.SERVICE_DELETING != current_state \
and GuestServices.SERVICE_NOT_CONFIGURED != current_state \
and GuestServices.SERVICE_CONFIGURED != current_state:
if GuestServices.SERVICE_DISABLING == state:
return GuestServices.SERVICE_DISABLING
if GuestServices.SERVICE_DELETING != current_state \
and GuestServices.SERVICE_NOT_CONFIGURED != current_state \
and GuestServices.SERVICE_CONFIGURED != current_state \
and GuestServices.SERVICE_DISABLING != current_state:
if GuestServices.SERVICE_DISABLED == state:
return GuestServices.SERVICE_DISABLED
if GuestServices.SERVICE_DELETING != current_state \
and GuestServices.SERVICE_NOT_CONFIGURED != current_state \
and GuestServices.SERVICE_CONFIGURED != current_state \
and GuestServices.SERVICE_DISABLING != current_state \
and GuestServices.SERVICE_DISABLED != current_state:
if GuestServices.SERVICE_ENABLING == state:
return GuestServices.SERVICE_ENABLING
if GuestServices.SERVICE_DELETING != current_state \
and GuestServices.SERVICE_NOT_CONFIGURED != current_state \
and GuestServices.SERVICE_CONFIGURED != current_state \
and GuestServices.SERVICE_DISABLING != current_state \
and GuestServices.SERVICE_DISABLED != current_state \
and GuestServices.SERVICE_ENABLING != current_state:
if GuestServices.SERVICE_ENABLED == state:
return GuestServices.SERVICE_ENABLED
return current_state
overall_state = None
for _, service_state in self._services.items():
overall_state = update_overall_state(overall_state, service_state)
return overall_state
@property
def communication_establish_timeout(self):
"""
Returns the maximum amount of time in seconds to wait for the guest
to establish communication, includes reboot time plus heartbeat
initialization time required
"""
restart_timeout = 300
if self._nfvi_guest_services is not None:
nfvi_service_name \
= self._get_nfvi_service_name(GUEST_SERVICE_NAME.HEARTBEAT)
for nfvi_service in self._nfvi_guest_services:
if nfvi_service_name == nfvi_service.name:
if 0 != nfvi_service.restart_timeout:
restart_timeout = nfvi_service.restart_timeout
break
return restart_timeout
def provision(self, service):
"""
Add a service to the list of known services
"""
if service not in self._services:
self._services[service] = GuestServices.SERVICE_NOT_CONFIGURED
def are_provisioned(self):
"""
Returns true if services have been provisioned
"""
return 0 < len(self._services)
def are_configured(self):
"""
Return true if all guest services are configured
"""
for service in self._services:
if GuestServices.SERVICE_NOT_CONFIGURED == self._services[service]:
return False
return True
def are_enabling(self):
"""
Return true if all guest services are enabling or are enabled
"""
for service in self._services:
if GuestServices.SERVICE_ENABLING != self._services[service]:
return False
return True
def are_enabled(self):
"""
Return true if all guest services are enabled
"""
for service in self._services:
if GuestServices.SERVICE_ENABLED != self._services[service]:
return False
return True
def are_disabling(self):
"""
Return true if all guest services are disabling or are disabled
"""
for service in self._services:
if GuestServices.SERVICE_DISABLING != self._services[service]:
return False
return True
def are_disabled(self):
"""
Return true if all guest services are disabled
"""
for service in self._services:
if GuestServices.SERVICE_DISABLED != self._services[service]:
return False
return True
def are_deleting(self):
"""
Return true if all guest services are deleting
"""
for service in self._services:
if GuestServices.SERVICE_DELETING != self._services[service]:
return False
return True
def configured(self):
"""
Set guest services to the configured state
"""
for service in self._services:
self._services[service] = GuestServices.SERVICE_CONFIGURED
def enable(self):
"""
Set guest services to the enabling state
"""
for service in self._services:
self._services[service] = GuestServices.SERVICE_ENABLING
def disable(self):
"""
Set guest services to the disabling state
"""
for service in self._services:
self._services[service] = GuestServices.SERVICE_DISABLING
def delete(self):
"""
Set guest services to the deleting state
"""
for service in self._services:
self._services[service] = GuestServices.SERVICE_DELETING
def deleted(self):
"""
Delete guest services
"""
if self._services is not None:
del self._services
self._services = dict()
def guest_communication_established(self):
"""
Returns true if guest communication has been established
"""
state = self._services.get(GUEST_SERVICE_NAME.HEARTBEAT, None)
return GuestServices.SERVICE_ENABLED == state
def get_nfvi_guest_service_names(self):
"""
Returns a listing of nfvi guest services and their state
"""
nfvi_service_names = list()
for service_name, service_state in self._services.items():
nfvi_name = self._get_nfvi_service_name(service_name)
if nfvi_name is not None:
nfvi_service_names.append(nfvi_name)
return nfvi_service_names
def get_nfvi_guest_services(self):
"""
Returns a listing of nfvi guest services and their state
"""
nfvi_services = list()
for service_name, service_state in self._services.items():
nfvi_name = self._get_nfvi_service_name(service_name)
nfvi_admin_state = self._get_nfvi_service_admin_state(service_state)
if nfvi_name is not None:
nfvi_service = dict()
nfvi_service['service'] = nfvi_name
nfvi_service['admin_state'] = nfvi_admin_state
nfvi_services.append(nfvi_service)
return nfvi_services
def nfvi_guest_services_update(self, nfvi_guest_services):
"""
NFVI Guest Services Update
"""
for nfvi_service in nfvi_guest_services:
# Preserve the restart-timeout, on disables it can be set to zero
if 0 == nfvi_service.restart_timeout \
and self._nfvi_guest_services is not None:
prev_nfvi_service \
= next((x for x in self._nfvi_guest_services
if x.name == nfvi_service.name), None)
if prev_nfvi_service is not None:
nfvi_service.restart_timeout \
= prev_nfvi_service.restart_timeout
service_name = self._convert_nfvi_service_name(nfvi_service.name)
service_state = self._convert_nfvi_service_state(
nfvi_service.admin_state, nfvi_service.oper_state)
if service_name is not None:
current_state = self._services.get(service_name, None)
if GuestServices.SERVICE_ENABLED == current_state:
if GuestServices.SERVICE_ENABLING == service_state:
self._services[service_name] = service_state
elif GuestServices.SERVICE_ENABLING == current_state:
if GuestServices.SERVICE_ENABLED == service_state:
self._services[service_name] = service_state
elif GuestServices.SERVICE_DISABLING == current_state:
if GuestServices.SERVICE_DISABLED == service_state:
self._services[service_name] = service_state
if self._nfvi_guest_services is not None:
del self._nfvi_guest_services
self._nfvi_guest_services = nfvi_guest_services
def nfvi_guest_services_state_update_needed(self):
"""
Returns true if the nfvi guest services needs to be updated
"""
if not self.are_configured():
return False
for nfvi_service in self._nfvi_guest_services:
service_name = self._convert_nfvi_service_name(nfvi_service.name)
service_state = self._services.get(service_name, None)
if service_state is not None:
expected_state \
= self._get_nfvi_service_admin_state(service_state)
if nfvi_service.admin_state != expected_state:
DLOG.verbose("Guest-Services update needed, "
"admin_state=%s, expected_admin_state=%s"
% (nfvi_service.admin_state, expected_state))
return True
return False
def as_dict(self):
"""
Represent Guest Services as dictionary
"""
data = dict()
data['state'] = self.state
data['services'] = self._services
data['nfvi_guest_services'] = list()
if self._nfvi_guest_services is not None:
for nfvi_service in self._nfvi_guest_services:
data['nfvi_guest_services'].append(nfvi_service.as_dict())
return data