Shawn Wang 7488940eed
Update Lb App Profile attributes
Current resource def for Lb App Profiles (HTTP, TCP, UDP) and their
counterparts in MP are incomplete and messy. Refactored related logic to
better separate different attributes for each profile type.

Change-Id: I11d0752484700cb55168a2fca5bf1a88926c8b81
2020-01-22 14:21:31 -08:00

595 lines
19 KiB
Python

# Copyright 2018 VMware, Inc.
# All Rights Reserved
#
# 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.
#
from distutils import version
from oslo_log import log as logging
from vmware_nsxlib.v3 import nsx_constants
from vmware_nsxlib.v3.policy import constants
from vmware_nsxlib.v3.policy.core_defs import ResourceDef
LOG = logging.getLogger(__name__)
TENANTS_PATH_PATTERN = "%s/"
LB_VIRTUAL_SERVERS_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-virtual-servers/"
LB_SERVICES_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-services/"
LB_POOL_PATH_PATTERN = TENANTS_PATH_PATTERN + "lb-pools/"
LB_APP_PROFILE_PATTERN = TENANTS_PATH_PATTERN + "lb-app-profiles/"
LB_MONITOR_PROFILE_PATTERN = TENANTS_PATH_PATTERN + "lb-monitor-profiles/"
LB_CLIENT_SSL_PROFILE_PATTERN = (TENANTS_PATH_PATTERN +
"lb-client-ssl-profiles/")
LBSERVER_SSL_PROFILE_PATTERN = (TENANTS_PATH_PATTERN +
"lb-server-ssl-profiles/")
LB_PERSISTENCE_PROFILE_PATTERN = (TENANTS_PATH_PATTERN +
"lb-persistence-profiles/")
class LBRuleDef(object):
def __init__(self, actions, match_conditions=None, name=None,
match_strategy=None, phase=None):
self.actions = actions
self.name = name
self.match_conditions = match_conditions
self.match_strategy = match_strategy
self.phase = phase
def get_obj_dict(self):
lb_rule = {
'actions': self.actions
}
if self.match_conditions:
lb_rule['match_conditions'] = self.match_conditions
if self.name:
lb_rule['display_name'] = self.name
if self.match_strategy:
lb_rule['match_strategy'] = self.match_strategy
if self.phase:
lb_rule['phase'] = self.phase
return lb_rule
class LBPoolMemberDef(object):
def __init__(self, ip_address, port=None, name=None,
weight=None, admin_state=None, backup_member=None):
self.name = name
self.ip_address = ip_address
self.port = port
self.weight = weight
self.admin_state = admin_state
self.backup_member = backup_member
def get_obj_dict(self):
body = {'ip_address': self.ip_address}
if self.name:
body['display_name'] = self.name
if self.ip_address:
body['port'] = self.port
if self.weight:
body['weight'] = self.weight
if self.admin_state:
body['admin_state'] = self.admin_state
if self.backup_member:
body['backup_member'] = self.backup_member
return body
class LBServerSslProfileDef(ResourceDef):
@property
def path_pattern(self):
return LBSERVER_SSL_PROFILE_PATTERN
@property
def path_ids(self):
return ('tenant', 'server_ssl_profile_id')
@staticmethod
def resource_type():
return "LBServerSslProfile"
def get_obj_dict(self):
body = super(LBServerSslProfileDef, self).get_obj_dict()
self._set_attrs_if_specified(body, ['cipher_group_label', 'ciphers',
'protocols',
'session_cache_enabled'])
return body
class LBClientSslProfileDef(ResourceDef):
@property
def path_pattern(self):
return LB_CLIENT_SSL_PROFILE_PATTERN
@property
def path_ids(self):
return ('tenant', 'client_ssl_profile_id')
@staticmethod
def resource_type():
return "LBClientSslProfile"
def get_obj_dict(self):
body = super(LBClientSslProfileDef, self).get_obj_dict()
self._set_attr_if_specified(body, 'protocols')
return body
class LBPersistenceProfileBase(ResourceDef):
@property
def path_pattern(self):
return LB_PERSISTENCE_PROFILE_PATTERN
@property
def path_ids(self):
return ('tenant', 'persistence_profile_id')
class LBCookiePersistenceProfileDef(LBPersistenceProfileBase):
@staticmethod
def resource_type():
return "LBCookiePersistenceProfile"
def get_obj_dict(self):
body = super(LBCookiePersistenceProfileDef, self).get_obj_dict()
self._set_attrs_if_specified(
body, ['cookie_garble', 'cookie_mode', 'cookie_name',
'cookie_path', 'cookie_time', 'persistence_shared'])
return body
class LBSourceIpPersistenceProfileDef(LBPersistenceProfileBase):
@staticmethod
def resource_type():
return "LBSourceIpPersistenceProfile"
def get_obj_dict(self):
body = super(LBSourceIpPersistenceProfileDef, self).get_obj_dict()
self._set_attrs_if_specified(
body, ['ha_persistence_mirroring_enabled', 'persistence_shared',
'purge', 'timeout'])
return body
class LBAppProfileBaseDef(ResourceDef):
@property
def path_pattern(self):
return LB_APP_PROFILE_PATTERN
@property
def path_ids(self):
return ('tenant', 'lb_app_profile_id')
def get_obj_dict(self):
body = super(LBAppProfileBaseDef, self).get_obj_dict()
self._set_attrs_if_specified(
body, ['idle_timeout'])
return body
class LBHttpProfileDef(LBAppProfileBaseDef):
@staticmethod
def resource_type():
return "LBHttpProfile"
def get_obj_dict(self):
body = super(LBHttpProfileDef, self).get_obj_dict()
self._set_attrs_if_specified(
body, ['http_redirect_to', 'http_redirect_to_https', 'ntlm',
'request_body_size', 'request_header_size',
'response_header_size', 'response_timeout',
'x_forwarded_for'])
return body
class LBFastTcpProfile(LBAppProfileBaseDef):
@staticmethod
def resource_type():
return "LBFastTcpProfile"
def get_obj_dict(self):
body = super(LBFastTcpProfile, self).get_obj_dict()
self._set_attrs_if_specified(
body, ['close_timeout', 'ha_flow_mirroring_enabled'])
return body
class LBFastUdpProfile(LBAppProfileBaseDef):
@staticmethod
def resource_type():
return "LBFastUdpProfile"
def get_obj_dict(self):
body = super(LBFastUdpProfile, self).get_obj_dict()
self._set_attrs_if_specified(
body, ['flow_mirroring_enabled'])
return body
class LBPoolDef(ResourceDef):
@property
def path_pattern(self):
return LB_POOL_PATH_PATTERN
@property
def path_ids(self):
return ('tenant', 'lb_pool_id')
@staticmethod
def resource_type():
return 'LBPool'
def get_obj_dict(self):
body = super(LBPoolDef, self).get_obj_dict()
self._set_attrs_if_specified(
body, ['active_monitor_paths',
'algorithm', 'member_group', 'snat_translation'])
members = self.get_attr('members')
if members is None:
members = []
if self.has_attr('members'):
members = members if isinstance(members, list) else [members]
body['members'] = []
for member in members:
# the list contains old json members and newly added member
if isinstance(member, LBPoolMemberDef):
member = member.get_obj_dict()
body['members'].append(member)
return body
class LBVirtualServerDef(ResourceDef):
@property
def path_pattern(self):
return LB_VIRTUAL_SERVERS_PATH_PATTERN
@property
def path_ids(self):
return ('tenant', 'virtual_server_id')
@staticmethod
def resource_type():
return 'LBVirtualServer'
def get_obj_dict(self):
body = super(LBVirtualServerDef, self).get_obj_dict()
self._set_attrs_if_specified(
body, ['ip_address', 'ports', 'max_concurrent_connections'])
client_ssl_binding = self.get_attr('client_ssl_profile_binding')
if client_ssl_binding:
self._set_attr_if_specified(
body, 'client_ssl_profile_binding',
value=client_ssl_binding)
server_ssl_binding = self.get_attr('server_ssl_profile_binding')
if server_ssl_binding:
self._set_attr_if_specified(
body, 'server_ssl_profile_binding',
value=server_ssl_binding)
waf_profile_binding = self.get_attr('waf_profile_binding')
if waf_profile_binding:
if isinstance(waf_profile_binding, WAFProfileBindingDef):
waf_profile_binding = waf_profile_binding.get_obj_dict()
self._set_attr_if_specified(
body, 'waf_profile_binding',
value=waf_profile_binding)
rules = self.get_attr('rules')
if self.has_attr('rules'):
rules = rules if isinstance(rules, list) else [rules]
body['rules'] = []
for rule in rules:
# the list contains old json rules and newly added ruledef rule
if isinstance(rule, LBRuleDef):
rule = rule.get_obj_dict()
body['rules'].append(rule)
app_profile_id = self.get_attr('application_profile_id')
if app_profile_id:
app_profile_def = LBAppProfileBaseDef(
lb_app_profile_id=app_profile_id, tenant=self.get_tenant())
body['application_profile_path'] = (
app_profile_def.get_resource_full_path())
if self.has_attr('lb_persistence_profile_id'):
path = ""
lb_persistence_profile_id = self.get_attr(
'lb_persistence_profile_id')
if lb_persistence_profile_id:
lb_persistence_profile_def = LBPersistenceProfileBase(
persistence_profile_id=lb_persistence_profile_id,
tenant=self.get_tenant())
path = lb_persistence_profile_def.get_resource_full_path()
body['lb_persistence_profile_path'] = path
if self.has_attr('lb_service_id'):
path = ""
lb_service_id = self.get_attr('lb_service_id')
if lb_service_id:
lb_service_def = LBServiceDef(
lb_service_id=lb_service_id, tenant=self.get_tenant())
path = lb_service_def.get_resource_full_path()
body['lb_service_path'] = path
if self.has_attr('pool_id'):
path = ""
lb_pool_id = self.get_attr('pool_id')
if lb_pool_id:
lb_pool_def = LBPoolDef(
lb_pool_id=lb_pool_id, tenant=self.get_tenant())
path = lb_pool_def.get_resource_full_path()
body['pool_path'] = path
if self.has_attr('access_list_control'):
lb_alc = self.get_attr('access_list_control')
if isinstance(lb_alc, LBAccessListControlDef):
self.attrs['access_list_control'] = lb_alc.get_obj_dict()
self._set_attrs_if_supported(body, ['access_list_control'])
return body
def _version_dependant_attr_supported(self, attr):
if (version.LooseVersion(self.nsx_version) >=
version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)):
if attr == 'access_list_control':
return True
LOG.warning(
"Ignoring %s for %s %s: this feature is not supported. "
"Current NSX version: %s. Minimum supported version: %s",
attr, self.resource_type, self.attrs.get('name', ''),
self.nsx_version, nsx_constants.NSX_VERSION_3_0_0)
return False
class ClientSSLProfileBindingDef(object):
def __init__(self, default_certificate_path, sni_certificate_paths=None,
ssl_profile_path=None, client_auth_ca_paths=None,
client_auth=None):
self.default_certificate_path = default_certificate_path
self.sni_certificate_paths = sni_certificate_paths
self.ssl_profile_path = ssl_profile_path
self.client_auth_ca_paths = client_auth_ca_paths
self.client_auth = client_auth
def get_obj_dict(self):
body = {
'default_certificate_path': self.default_certificate_path
}
if self.sni_certificate_paths:
body['sni_certificate_paths'] = self.sni_certificate_paths
if self.ssl_profile_path:
body['ssl_profile_path'] = self.ssl_profile_path
if self.client_auth_ca_paths:
body['client_auth_ca_paths'] = self.client_auth_ca_paths
if self.client_auth:
body['client_auth'] = self.client_auth
return body
class ServerSSLProfileBindingDef(object):
def __init__(self, client_certificate_path=None,
certificate_chain_depth=None,
server_auth=None, server_auth_ca_paths=None,
server_auth_crl_paths=None, ssl_profile_path=None):
self.client_certificate_path = client_certificate_path
self.certificate_chain_depth = certificate_chain_depth
self.server_auth = server_auth
self.server_auth_ca_paths = server_auth_ca_paths
self.server_auth_crl_paths = server_auth_crl_paths
self.ssl_profile_path = ssl_profile_path
def get_obj_dict(self):
body = {}
if self.client_certificate_path:
body['client_certificate_path'] = self.client_certificate_path
if self.ssl_profile_path:
body['certificate_chain_depth'] = self.certificate_chain_depth
if self.server_auth:
body['server_auth'] = self.server_auth
if self.ssl_profile_path:
body['server_auth_ca_paths'] = self.server_auth_ca_paths
if self.server_auth_crl_paths:
body['server_auth_crl_paths'] = self.server_auth_crl_paths
if self.ssl_profile_path:
body['ssl_profile_path'] = self.ssl_profile_path
return body
class WAFProfileBindingDef(object):
def __init__(self, waf_profile_path,
operational_mode=constants.WAF_OPERATIONAL_MODE_PROTECTION,
debug_log_level=constants.WAF_LOG_LEVEL_NO_LOG):
self.waf_profile_path = waf_profile_path
self.operational_mode = operational_mode
self.debug_log_level = debug_log_level
def get_obj_dict(self):
body = {
'waf_profile_path': self.waf_profile_path,
'operational_mode': self.operational_mode,
'debug_log_level': self.debug_log_level
}
return body
class LBServiceDef(ResourceDef):
@property
def path_pattern(self):
return LB_SERVICES_PATH_PATTERN
@property
def path_ids(self):
return ('tenant', 'lb_service_id')
@staticmethod
def resource_type():
return 'LBService'
def get_obj_dict(self):
body = super(LBServiceDef, self).get_obj_dict()
self._set_attrs_if_specified(body, ['size', 'connectivity_path'])
self._set_attrs_if_supported(body, ['relax_scale_validation'])
return body
def _version_dependant_attr_supported(self, attr):
if (version.LooseVersion(self.nsx_version) >=
version.LooseVersion(nsx_constants.NSX_VERSION_3_0_0)):
if attr == 'relax_scale_validation':
return True
else:
LOG.warning(
"Ignoring %s for %s %s: this feature is not supported."
"Current NSX version: %s. Minimum supported version: %s",
attr, self.resource_type, self.attrs.get('name', ''),
self.nsx_version, nsx_constants.NSX_VERSION_3_0_0)
return False
return False
class LBServiceStatisticsDef(ResourceDef):
@property
def path_pattern(self):
return LB_SERVICES_PATH_PATTERN + '%s/statistics/'
@property
def path_ids(self):
return ('tenant', 'lb_service_id', '')
class LBServiceStatusDef(ResourceDef):
@property
def path_pattern(self):
return LB_SERVICES_PATH_PATTERN + '%s/detailed-status/'
@property
def path_ids(self):
return ('tenant', 'lb_service_id', '')
class LBServiceUsageDef(ResourceDef):
def __init__(self, **kwargs):
self.realtime = kwargs.pop('realtime')
super(LBServiceUsageDef, self).__init__(**kwargs)
@property
def path_pattern(self):
if self.realtime:
return (LB_SERVICES_PATH_PATTERN +
'%s/service-usage?source=realtime')
return LB_SERVICES_PATH_PATTERN + '%s/service-usage/'
@property
def path_ids(self):
return ('tenant', 'lb_service_id', '')
class LBVirtualServerStatusDef(ResourceDef):
@property
def path_pattern(self):
return (LB_SERVICES_PATH_PATTERN +
'%s/lb-virtual-servers/%s/detailed-status/')
@property
def path_ids(self):
return ('tenant', 'lb_service_id', 'lb_virtual_server_id', '')
class LBMonitorProfileBaseDef(ResourceDef):
addl_attrs = ['interval', 'timeout', 'fall_count', 'rise_count']
@property
def path_pattern(self):
return LB_MONITOR_PROFILE_PATTERN
@property
def path_ids(self):
return ('tenant', 'lb_monitor_profile_id')
def get_obj_dict(self):
body = super(LBMonitorProfileBaseDef, self).get_obj_dict()
self._set_attrs_if_specified(body, self.addl_attrs)
return body
class LBHttpMonitorProfileDef(LBMonitorProfileBaseDef):
addl_attrs = LBMonitorProfileBaseDef.addl_attrs + [
'monitor_port', 'request_url', 'request_method', 'request_version',
'request_headers', 'request_body', 'response_status_codes']
@staticmethod
def resource_type():
return "LBHttpMonitorProfile"
class LBHttpsMonitorProfileDef(LBHttpMonitorProfileDef):
@staticmethod
def resource_type():
return "LBHttpsMonitorProfile"
class LBUdpMonitorProfileDef(LBMonitorProfileBaseDef):
addl_attrs = LBMonitorProfileBaseDef.addl_attrs + [
'monitor_port', 'receive', 'send']
@staticmethod
def resource_type():
return "LBUdpMonitorProfile"
class LBIcmpMonitorProfileDef(LBMonitorProfileBaseDef):
@staticmethod
def resource_type():
return "LBIcmpMonitorProfile"
class LBTcpMonitorProfileDef(LBMonitorProfileBaseDef):
addl_attrs = LBMonitorProfileBaseDef.addl_attrs + ['monitor_port']
@staticmethod
def resource_type():
return "LBTcpMonitorProfile"
class LBAccessListControlDef(object):
def __init__(self, action, group_path, enabled=None):
self.action = action
self.group_path = group_path
self.enabled = enabled
def get_obj_dict(self):
access_list_control = {
'action': self.action,
'group_path': self.group_path
}
if self.enabled is not None:
access_list_control['enabled'] = self.enabled
return access_list_control