config/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/firewallrules.py

222 lines
7.7 KiB
Python

# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import os
import pecan
from pecan import expose
from pecan import rest
import wsme
import wsmeext.pecan as wsme_pecan
from wsme import types as wtypes
from sysinv import objects
from sysinv.api.controllers.v1 import utils
from sysinv.api.controllers.v1 import base
from sysinv.api.controllers.v1 import collection
from sysinv.api.controllers.v1 import link
from sysinv.api.controllers.v1 import types
from sysinv.common import constants
from sysinv.common import exception
from sysinv.common import utils as cutils
from sysinv.openstack.common import log
from sysinv.openstack.common.gettextutils import _
LOG = log.getLogger(__name__)
LOCK_NAME = 'FirewallRulesController'
class FirewallRules(base.APIBase):
"""API representation of oam custom firewall rules.
This class enforces type checking and value constraints, and converts
between the internal object model and the API representation of
oam custom firewall rules.
"""
uuid = types.uuid
"Unique UUID for the firewall rules"
firewall_sig = wtypes.text
"Represents the signature of the custom firewall rules"
created_at = wtypes.datetime.datetime
updated_at = wtypes.datetime.datetime
def __init__(self, **kwargs):
self.fields = list(objects.firewallrules.fields.keys())
for k in self.fields:
if not hasattr(self, k):
continue
setattr(self, k, kwargs.get(k, wtypes.Unset))
self.fields.append('firewall_sig')
setattr(self, 'firewall_sig', kwargs.get('value', None))
@classmethod
def convert_with_links(cls, rpc_firewallrules, expand=True):
parm = FirewallRules(**rpc_firewallrules.as_dict())
if not expand:
parm.unset_fields_except(['uuid', 'firewall_sig', 'updated_at'])
parm.links = [link.Link.make_link('self', pecan.request.host_url,
'parameters', parm.uuid),
link.Link.make_link('bookmark',
pecan.request.host_url,
'parameters', parm.uuid,
bookmark=True)
]
return parm
def firewallrules_as_dict(sp_firewallrules):
sp_firewallrules_dict = sp_firewallrules.as_dict()
keys = objects.firewallrules.fields.keys()
for k, v in sp_firewallrules.as_dict().items():
if k == 'value':
sp_firewallrules_dict['firewall_sig'] = \
sp_firewallrules_dict.pop('value')
elif k not in keys:
sp_firewallrules_dict.pop(k)
return sp_firewallrules_dict
class FirewallRulesCollection(collection.Collection):
"""API representation of a collection of firewall rules."""
firewallrules = [FirewallRules]
"A list containing firewallrules objects"
def __init__(self, **kwargs):
self._type = 'firewallrules'
@classmethod
def convert_with_links(cls, rpc_firewallrules, limit, url=None,
expand=False,
**kwargs):
collection = FirewallRulesCollection()
collection.firewallrules = [FirewallRules.convert_with_links(p, expand)
for p in rpc_firewallrules]
collection.next = collection.get_next(limit, url=url, **kwargs)
return collection
class FirewallRulesController(rest.RestController):
"""REST controller for Custom Firewall Rules."""
_custom_actions = {
'import_firewall_rules': ['POST'],
}
def __init__(self):
self._api_token = None
@wsme_pecan.wsexpose(FirewallRules, types.uuid)
def get_one(self, firewallrules_uuid):
"""Retrieve information about the given firewall rules."""
try:
sp_firewallrules = objects.firewallrules.get_by_uuid(
pecan.request.context, firewallrules_uuid)
except exception.InvalidParameterValue:
raise wsme.exc.ClientSideError(
_("No firewall rules found for %s" % firewallrules_uuid))
return FirewallRules.convert_with_links(sp_firewallrules)
def _get_firewallrules_collection(self, marker, limit,
sort_key, sort_dir, expand=False,
resource_url=None):
limit = utils.validate_limit(limit)
sort_dir = utils.validate_sort_dir(sort_dir)
sp_firewallrules = pecan.request.dbapi.service_parameter_get_one(
service=constants.SERVICE_TYPE_PLATFORM,
section=constants.SERVICE_PARAM_SECTION_PLATFORM_SYSINV,
name=constants.SERVICE_PARAM_NAME_SYSINV_FIREWALL_RULES_ID)
sp_firewallrules.firewall_sig = sp_firewallrules.value
sp_firewallrules = [sp_firewallrules]
rules = FirewallRulesCollection.convert_with_links(
sp_firewallrules,
limit,
url=resource_url,
expand=expand,
sort_key=sort_key,
sort_dir=sort_dir)
return rules
@wsme_pecan.wsexpose(FirewallRulesCollection, types.uuid, types.uuid, int,
wtypes.text, wtypes.text)
def get_all(self, isystem_uuid=None, marker=None, limit=None,
sort_key='id', sort_dir='asc'):
"""Retrieve a list of firewallrules. Only one per system"""
sort_key = ['section', 'name']
return self._get_firewallrules_collection(marker, limit,
sort_key, sort_dir)
@expose('json')
@cutils.synchronized(LOCK_NAME)
def import_firewall_rules(self, file):
file = pecan.request.POST['file']
if not file.filename:
return dict(success="", error="Error: No firewall rules uploaded")
# Check if the firewallrules_file size is large
try:
_check_firewall_rules_file_size(file)
except Exception as e:
LOG.exception(e)
return dict(success="", error=e.message)
file.file.seek(0, os.SEEK_SET)
contents = file.file.read()
# Get OAM network ip version
oam_network = pecan.request.dbapi.network_get_by_type(
constants.NETWORK_TYPE_OAM)
oam_address_pool = pecan.request.dbapi.address_pool_get(
oam_network.pool_uuid)
try:
firewall_sig = pecan.request.rpcapi.update_firewall_config(
pecan.request.context, oam_address_pool.family, contents)
# push the updated firewall_sig into db
sp_firewallrules = pecan.request.dbapi.service_parameter_get_one(
service=constants.SERVICE_TYPE_PLATFORM,
section=constants.SERVICE_PARAM_SECTION_PLATFORM_SYSINV,
name=constants.SERVICE_PARAM_NAME_SYSINV_FIREWALL_RULES_ID)
sp_firewallrules = pecan.request.dbapi.service_parameter_update(
sp_firewallrules.uuid,
{'value': firewall_sig, 'personality': constants.CONTROLLER})
sp_firewallrules_dict = firewallrules_as_dict(sp_firewallrules)
LOG.info("import_firewallrules sp_firewallrules={}".format(
sp_firewallrules_dict))
except Exception as e:
return dict(success="", error=e.value)
return dict(success="", error="", body="",
firewallrules=sp_firewallrules_dict)
def _check_firewall_rules_file_size(firewallrules_file):
firewallrules_file.file.seek(0, os.SEEK_END)
size = firewallrules_file.file.tell()
if size > constants.FIREWALL_RULES_MAX_FILE_SIZE:
raise wsme.exc.ClientSideError(
_("Firewall rules file size exceeded maximum supported"
" size of %s bytes." % constants.FIREWALL_RULES_MAX_FILE_SIZE))