# Copyright 2016 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 oslo_log import log from requests import exceptions as requests_exceptions from vmware_nsxlib.v3 import exceptions as v3_exceptions LOG = log.getLogger(__name__) class ExceptionConfig(object): def __init__(self): # When hit during API call, these exceptions will mark # endpoint as DOWN immediately # This setting has no effect on keepalive validation self.ground_triggers = [requests_exceptions.ConnectionError, requests_exceptions.Timeout] # When hit during API call, these exceptions will be # retried with next available endpoint # When hit during validation, these exception will not # mark endpoint as DOWN self.retriables = [v3_exceptions.APITransactionAborted, v3_exceptions.CannotConnectToServer, v3_exceptions.ServerBusy] # When hit during API call, these exceptions will be retried # after the endpoints are regenerated with up-to-date auth # credentials / tokens self.regenerate_triggers = [v3_exceptions.InvalidCredentials, v3_exceptions.ClientCertificateNotTrusted, v3_exceptions.BadXSRFToken] def should_ground_endpoint(self, ex): for exception in self.ground_triggers: if isinstance(ex, exception): return True return False def should_retry(self, ex): for exception in self.retriables: if isinstance(ex, exception): return True return False def should_regenerate(self, ex): for exception in self.regenerate_triggers: if isinstance(ex, exception): return True return False class NsxLibConfig(object): """Class holding all the configuration parameters used by the nsxlib code. :param nsx_api_managers: List of IP addresses of the NSX managers. Each IP address should be of the form: [://][:] If scheme is not provided https is used. If port is not provided port 80 is used for http and port 443 for https. :param username: User name for the NSX manager :param password: Password for the NSX manager :param client_cert_provider: None, or ClientCertProvider object. If specified, nsxlib will use client cert auth instead of basic authentication. :param insecure: If true, the NSX Manager server certificate is not verified. If false the CA bundle specified via "ca_file" will be used or if unset the "thumbprint" will be used. If "thumbprint" is unset, the default system root CAs will be used. :param ca_file: Specify a CA bundle file to use in verifying the NSX Manager server certificate. This option is ignored if "insecure" is set to True. If "insecure" is set to False and "ca_file" is unset, the "thumbprint" will be used. If "thumbprint" is unset, the system root CAs will be used to verify the server certificate. :param thumbprint: Specify a thumbprint string to use in verifying the NSX Manager server certificate. This option is ignored if "insecure" is set to True or "ca_file" is defined. :param token_provider: None, or instance of implemented AbstractJWTProvider which will return the JSON Web Token used in the requests in NSX for authorization. :param concurrent_connections: Maximum concurrent connections to each NSX manager. :param retries: Maximum number of times to retry a HTTP connection. :param http_timeout: The time in seconds before aborting a HTTP connection to a NSX manager. :param http_read_timeout: The time in seconds before aborting a HTTP read response from a NSX manager. :param conn_idle_timeout: The amount of time in seconds to wait before ensuring connectivity to the NSX manager if no manager connection has been used. :param http_provider: HTTPProvider object, or None. :param max_attempts: Maximum number of times to retry API requests upon stale revision errors. :param plugin_scope: The default scope for the v3 api-version tag :param plugin_tag: The value for the v3 api-version tag :param plugin_ver: The version of the plugin used as the 'os-api-version' tag value in the v3 api-version tag :param dns_nameservers: List of nameservers to configure for the DHCP binding entries. These will be used if there are no nameservers defined on the subnet. :param dns_domain: Domain to use for building the hostnames. :param allow_overwrite_header: If True, a default header of X-Allow-Overwrite:true will be added to all the requests, to allow admin user to update/ delete all entries. :param rate_limit_retry: If True, the client will retry requests failed on "Too many requests" error. :param cluster_unavailable_retry: If True, skip fatal errors when no endpoint in the NSX management cluster is available to serve a request, and retry the request instead. This setting can not be False if single endpoint is configured in the cluster, since there will be no keepalive probes in this case. :param api_rate_limit_per_endpoint: If set to positive integer, API calls sent to each endpoint will be limited to a max rate of this value per second. The rate limit is not enforced on connection validations. This option defaults to None, which disables rate limit. :param api_rate_mode: Algorithm used to adaptively adjust max API rate limit. If not set, the max rate will not be automatically changed. If set to 'AIMD', max API rate will be increase by 1 after successful calls that was blocked before sent, and will be decreased by half after 429/503 error for each period. The rate has hard max limit of min(100/s, param api_rate_limit_per_endpoint). :param api_log_mode: Option to collect API call logs within nsxlib. When set to API_LOG_PER_CLUSTER, API calls sent to all endpoints will be collected at one place. When set to API_LOG_PER_ENDPOINT, API calls sent to each endpoint will be collected individually. By default, this option is disabled as set to None. -- Additional parameters which are relevant only for the Policy manager: :param allow_passthrough: If True, use nsx manager api for cases which are not supported by the policy manager api. :param realization_max_attempts: Maximum number of times to retry while waiting for a resource to be realized. :param realization_wait_sec: Number of seconds to wait between attempts for a resource to be realized. """ def __init__(self, nsx_api_managers=None, username=None, password=None, client_cert_provider=None, insecure=True, ca_file=None, thumbprint=None, token_provider=None, concurrent_connections=10, retries=3, http_timeout=10, http_read_timeout=180, conn_idle_timeout=10, http_provider=None, max_attempts=10, plugin_scope=None, plugin_tag=None, plugin_ver=None, dns_nameservers=None, dns_domain='openstacklocal', allow_overwrite_header=False, rate_limit_retry=True, cluster_unavailable_retry=False, allow_passthrough=False, realization_max_attempts=50, realization_wait_sec=1.0, api_rate_limit_per_endpoint=None, api_rate_mode=None, exception_config=None, api_log_mode=None): self.nsx_api_managers = nsx_api_managers self._username = username self._password = password self._ca_file = ca_file self._thumbprint = thumbprint self.insecure = insecure self.concurrent_connections = concurrent_connections self.retries = retries self.http_timeout = http_timeout self.http_read_timeout = http_read_timeout self.conn_idle_timeout = conn_idle_timeout self.http_provider = http_provider self.client_cert_provider = client_cert_provider self.token_provider = token_provider self.max_attempts = max_attempts self.plugin_scope = plugin_scope self.plugin_tag = plugin_tag self.plugin_ver = plugin_ver self.dns_nameservers = dns_nameservers or [] self.dns_domain = dns_domain self.allow_overwrite_header = allow_overwrite_header self.rate_limit_retry = rate_limit_retry self.cluster_unavailable_retry = cluster_unavailable_retry self.allow_passthrough = allow_passthrough self.realization_max_attempts = realization_max_attempts self.realization_wait_sec = realization_wait_sec self.api_rate_limit_per_endpoint = api_rate_limit_per_endpoint self.api_rate_mode = api_rate_mode self.exception_config = exception_config or ExceptionConfig() self.api_log_mode = api_log_mode if len(nsx_api_managers) == 1 and not self.cluster_unavailable_retry: LOG.warning("When only one endpoint is provided, keepalive probes" " are disabled. For the system to be able to recover" " from DOWN state, cluster_unavailable_retry is set" " to True, overriding provided configuration") self.cluster_unavailable_retry = True if len(nsx_api_managers) > self.max_attempts: LOG.warning("max_attempts setting (%d) is lower than amount of" " endpoints (%d), which means that not all endpoints" " will be probed in case of retriable error", self.max_attempts, len(nsx_api_managers)) def extend(self, keepalive_section, validate_connection_method=None, url_base=None): if keepalive_section or validate_connection_method: LOG.warning("keepalive_section and validate_connection_method are" " no longer used to conduct keepalive probes. For" " most efficient keepalive roundtrip, proxy health" " API is always used.") self.url_base = url_base def _attribute_by_index(self, scalar_or_list, index): if isinstance(scalar_or_list, list): if not len(scalar_or_list): return None if len(scalar_or_list) > index: return scalar_or_list[index] # if not long enough - use the first one as default return scalar_or_list[0] # this is a scalar return scalar_or_list def username(self, index): return self._attribute_by_index(self._username, index) def password(self, index): return self._attribute_by_index(self._password, index) def ca_file(self, index): return self._attribute_by_index(self._ca_file, index) def thumbprint(self, index): return self._attribute_by_index(self._thumbprint, index)