config/sysinv/sysinv/sysinv/sysinv/puppet/base.py

225 lines
6.7 KiB
Python

#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import collections
import abc
import itertools
import netaddr
import os
import six
from sqlalchemy.orm.exc import NoResultFound
from sysinv.common import constants
from sysinv.common import utils
from sysinv.common import exception
@six.add_metaclass(abc.ABCMeta)
class BasePuppet(object):
"""Base class to encapsulate puppet operations for hiera configuration"""
CONFIG_WORKDIR = '/tmp/config'
DEFAULT_REGION_NAME = 'RegionOne'
DEFAULT_SERVICE_PROJECT_NAME = 'services'
SYSTEM_CONTROLLER_SERVICES = [
'keystone',
'glance',
'nova',
'neutron',
'cinder',
'dcorch'
]
def __init__(self, operator):
self._operator = operator
@property
def dbapi(self):
return self._operator.dbapi
@property
def context(self):
return self._operator.context
@staticmethod
def _generate_random_password(length=16):
suffix = "Ti0*"
num = (length / 2) - len(suffix) / 2
return os.urandom(num).encode('hex') + suffix
def _get_system(self):
system = self.context.get('_system', None)
if system is None:
system = self.dbapi.isystem_get_one()
self.context['_system'] = system
return system
def _sdn_enabled(self):
if self.dbapi is None:
return False
system = self._get_system()
return system.capabilities.get('sdn_enabled', False)
def _https_enabled(self):
if self.dbapi is None:
return False
system = self._get_system()
return system.capabilities.get('https_enabled', False)
def _region_config(self):
if self.dbapi is None:
return False
system = self._get_system()
return system.capabilities.get('region_config', False)
def _distributed_cloud_role(self):
if self.dbapi is None:
return None
system = self._get_system()
return system.distributed_cloud_role
def _region_name(self):
"""Returns the local region name of the system"""
if self.dbapi is None:
return self.DEFAULT_REGION_NAME
system = self._get_system()
return system.region_name
def _get_service_project_name(self):
if self.dbapi is None:
return self.DEFAULT_SERVICE_PROJECT_NAME
system = self._get_system()
return system.service_project_name
def _get_service(self, service_name):
if self.dbapi is None:
return None
try:
service = self.dbapi.service_get(service_name)
except exception.ServiceNotFound:
# service not configured
return None
return service
def _get_shared_services(self):
if self.dbapi is None:
return []
system = self._get_system()
return system.capabilities.get('shared_services', [])
def _get_address_by_name(self, name, networktype):
"""
Retrieve an address entry by name and scoped by network type
"""
addresses = self.context.setdefault('_address_names', {})
address_name = utils.format_address_name(name, networktype)
address = addresses.get(address_name)
if address is None:
address = self.dbapi.address_get_by_name(address_name)
addresses[address_name] = address
return address
def _get_management_address(self):
address = self._get_address_by_name(
constants.CONTROLLER_HOSTNAME, constants.NETWORK_TYPE_MGMT)
return address.address
def _get_pxeboot_address(self):
address = self._get_address_by_name(
constants.CONTROLLER_HOSTNAME, constants.NETWORK_TYPE_PXEBOOT)
return address.address
def _get_oam_address(self):
address = self._get_address_by_name(
constants.CONTROLLER_HOSTNAME, constants.NETWORK_TYPE_OAM)
return address.address
def _get_host_cpu_list(self, host, function=None, threads=False):
"""
Retreive a list of CPUs for the host, filtered by function and thread
siblings (if supplied)
"""
cpus = []
for c in self.dbapi.icpu_get_by_ihost(host.id):
if c.thread != 0 and not threads:
continue
if c.allocated_function == function or not function:
cpus.append(c)
return cpus
def _get_service_parameters(self, service=None):
service_parameters = []
if self.dbapi is None:
return service_parameters
try:
service_parameters = self.dbapi.service_parameter_get_all(
service=service)
# the service parameter has not been added
except NoResultFound:
pass
return service_parameters
@staticmethod
def _service_parameter_lookup_one(service_parameters, section, name,
default):
for param in service_parameters:
if param['section'] == section and param['name'] == name:
return param['value']
return default
def _format_service_parameter(self, service_parameters, section, group, name):
parameter = {}
key = group + name
value = self._service_parameter_lookup_one(service_parameters, section,
name, 'undef')
if value != 'undef':
parameter[key] = value
return parameter
@staticmethod
def _format_url_address(address):
"""Format the URL address according to RFC 2732"""
try:
addr = netaddr.IPAddress(address)
if addr.version == constants.IPV6_FAMILY:
return "[%s]" % address
else:
return str(address)
except netaddr.AddrFormatError:
return address
@staticmethod
def _format_range_set(items):
# Generate a pretty-printed value of ranges, such as 3-6,8-9,12-17
ranges = []
for k, iterable in itertools.groupby(enumerate(sorted(items)),
lambda x: x[1] - x[0]):
rng = list(iterable)
if len(rng) == 1:
s = str(rng[0][1])
else:
s = "%s-%s" % (rng[0][1], rng[-1][1])
ranges.append(s)
return ','.join(ranges)
def _get_numa_index_list(self, obj):
"""Create map of objects indexed by numa node"""
obj_lists = collections.defaultdict(list)
for index, o in enumerate(obj):
o["_index"] = index
obj_lists[o.numa_node].append(o)
return obj_lists