-
Notifications
You must be signed in to change notification settings - Fork 4
Mitaka 21st march base latency optimized #416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: mitaka_21st_march_base
Are you sure you want to change the base?
Changes from all commits
2e02eac
ea35531
6a245c4
ede12d8
d49491c
06ecaed
ade56e7
c988e99
24f1be8
d3f6265
eb2f863
a8b4edd
377e3d2
6a729e2
fa8f7f0
06e66ec
ea0fa4b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| # limitations under the License. | ||
|
|
||
| import eventlet | ||
| from eventlet import greenpool | ||
| from keystoneclient import exceptions as k_exceptions | ||
| from keystoneclient.v2_0 import client as keyclient | ||
| from neutron._i18n import _LE | ||
|
|
@@ -38,6 +39,7 @@ | |
| from gbpservice.nfp.common import constants as nfp_constants | ||
| from gbpservice.nfp.common import topics as nfp_rpc_topics | ||
|
|
||
| from gbpservice.neutron.services.grouppolicy.common import constants as gp_constants | ||
|
|
||
| NFP_NODE_DRIVER_OPTS = [ | ||
| cfg.BoolOpt('is_service_admin_owned', | ||
|
|
@@ -59,7 +61,6 @@ | |
|
|
||
| LOG = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class InvalidServiceType(exc.NodeCompositionPluginBadRequest): | ||
| message = _("The NFP Node driver only supports the services " | ||
| "VPN, Firewall and LB in a Service Chain") | ||
|
|
@@ -227,6 +228,9 @@ class NFPNodeDriver(driver_base.NodeDriverBase): | |
| def __init__(self): | ||
| super(NFPNodeDriver, self).__init__() | ||
| self._lbaas_plugin = None | ||
| self.thread_pool = greenpool.GreenPool(10) | ||
| self.active_threads = [] | ||
| self.sc_node_count = 0 | ||
|
|
||
| @property | ||
| def name(self): | ||
|
|
@@ -336,8 +340,18 @@ def create(self, context): | |
| self._set_node_instance_network_function_map( | ||
| context.plugin_session, context.current_node['id'], | ||
| context.instance['id'], network_function_id) | ||
| self._wait_for_network_function_operation_completion( | ||
| context, network_function_id, operation='create') | ||
|
|
||
| # Check for NF status in a separate thread | ||
| gth = self.thread_pool.spawn(self._wait_for_network_function_operation_completion, | ||
| context, network_function_id, operation='create') | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use proper naming, green_threads instead of gth |
||
|
|
||
| self.active_threads.append(gth) | ||
|
|
||
| # At last wait for the threads to complete, success/failure/timeout | ||
| if len(self.active_threads) == self.sc_node_count: | ||
| for gth in self.active_threads: | ||
| gth.wait() | ||
| self.active_threads = [] | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't we need same thread waiting in update and delete also ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: No other path is optimized, only create path is optimized. |
||
| def update(self, context): | ||
| context._plugin_context = self._get_resource_owner_context( | ||
|
|
@@ -591,23 +605,49 @@ def _get_service_targets(self, context): | |
| {'service_type': service_type}) | ||
| raise Exception("Service Targets are not created for the Node") | ||
|
|
||
| service_target_info = {'provider_ports': [], 'provider_pts': [], | ||
| 'consumer_ports': [], 'consumer_pts': []} | ||
| service_target_info = { | ||
| 'provider_ports': [], | ||
| 'provider_subnet': None, | ||
| 'provider_pts': [], | ||
| 'provider_pt_objs': [], | ||
| 'provider_ptg': [], | ||
| 'consumer_ports': [], | ||
| 'consumer_subnet': None, | ||
| 'consumer_pts': [], | ||
| 'consumer_pt_objs': [], | ||
| 'consumer_ptg': []} | ||
|
|
||
| for service_target in provider_service_targets: | ||
| policy_target = context.gbp_plugin.get_policy_target( | ||
| context.plugin_context, service_target.policy_target_id) | ||
| policy_target_group = context.gbp_plugin.get_policy_target_group( | ||
| context.plugin_context, policy_target['policy_target_group_id']) | ||
| port = context.core_plugin.get_port( | ||
| context.plugin_context, policy_target['port_id']) | ||
| port['ip_address'] = port['fixed_ips'][0]['ip_address'] | ||
| subnet = context.core_plugin.get_subnet( | ||
| context.plugin_context, port['fixed_ips'][0]['subnet_id']) | ||
| service_target_info['provider_ports'].append(port) | ||
| service_target_info['provider_subnet'] = subnet | ||
| service_target_info['provider_pts'].append(policy_target['id']) | ||
| service_target_info['provider_pt_objs'].append(policy_target) | ||
| service_target_info['provider_ptg'].append(policy_target_group) | ||
|
|
||
| for service_target in consumer_service_targets: | ||
| policy_target = context.gbp_plugin.get_policy_target( | ||
| context.plugin_context, service_target.policy_target_id) | ||
| policy_target_group = context.gbp_plugin.get_policy_target_group( | ||
| context.plugin_context, policy_target['policy_target_group_id']) | ||
| port = context.core_plugin.get_port( | ||
| context.plugin_context, policy_target['port_id']) | ||
| port['ip_address'] = port['fixed_ips'][0]['ip_address'] | ||
| subnet = context.core_plugin.get_subnet( | ||
| context.plugin_context, port['fixed_ips'][0]['subnet_id']) | ||
| service_target_info['consumer_ports'].append(port) | ||
| service_target_info['consumer_subnet'] = subnet | ||
| service_target_info['consumer_pts'].append(policy_target['id']) | ||
| service_target_info['consumer_pt_objs'].append(policy_target) | ||
| service_target_info['consumer_ptg'].append(policy_target_group) | ||
|
|
||
| return service_target_info | ||
|
|
||
|
|
@@ -619,6 +659,7 @@ def _is_node_order_in_spec_supported(self, context): | |
| for spec in current_specs: | ||
| node_list.extend(spec['nodes']) | ||
|
|
||
| self.sc_node_count = len(node_list) | ||
| for node_id in node_list: | ||
| node_info = context.sc_plugin.get_servicechain_node( | ||
| context.plugin_context, node_id) | ||
|
|
@@ -641,9 +682,65 @@ def _is_node_order_in_spec_supported(self, context): | |
| raise InvalidNodeOrderInChain( | ||
| node_order=allowed_chain_combinations) | ||
|
|
||
| def _get_consumers_for_provider(self, context, provider): | ||
| ''' | ||
| { | ||
| consuming_ptgs_details: [{'ptg': <>, 'subnets': <>}] | ||
| consuming_eps_details: [] | ||
| } | ||
| ''' | ||
|
|
||
| consuming_ptgs_details = [] | ||
| consuming_eps_details = [] | ||
|
|
||
| provided_prs_id = provider['provided_policy_rule_sets'][0] | ||
| provided_prs = context.gbp_plugin.get_policy_rule_set( | ||
| context.plugin_context, provided_prs_id) | ||
| consuming_ptg_ids = provided_prs['consuming_policy_target_groups'] | ||
| consuming_ep_ids = provided_prs['consuming_external_policies'] | ||
|
|
||
| consuming_ptgs = context.gbp_plugin.get_policy_target_groups( | ||
| context.plugin_context, filters={'id':consuming_ptg_ids}) | ||
| consuming_eps_details = context.gbp_plugin.get_external_policies( | ||
| context.plugin_context, filters={'id': consuming_ep_ids}) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If no external policies available, it'll return empty list, no need to define that above.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. readability. |
||
|
|
||
| for ptg in consuming_ptgs: | ||
| subnet_ids = ptg['subnets'] | ||
| subnets = context.core_plugin.get_subnets(context.plugin_context, filters={'id':subnet_ids}) | ||
| consuming_ptgs_details.append({'ptg':ptg, 'subnets':subnets}) | ||
|
|
||
| return consuming_ptgs_details, consuming_eps_details | ||
|
|
||
|
|
||
| def _create_network_function(self, context): | ||
| """ | ||
| nfp_create_nf_data :- | ||
|
|
||
| {'resource_owner_context': <>, | ||
| 'service_chain_instance': <>, | ||
| 'service_chain_node': <>, | ||
| 'service_profile': <>, | ||
| 'service_config': context.current_node.get('config'), | ||
| 'provider': {'pt':<>, 'ptg':<>, 'port':<>, 'subnet':<>}, | ||
| 'consumer': {'pt':<>, 'ptg':<>, 'port':<>, 'subnet':<>}, | ||
| 'management': {'pt':<>, 'ptg':<>, 'port':<>, 'subnet':<>}, | ||
| 'management_ptg_id': <>, | ||
| 'network_function_mode': nfp_constants.GBP_MODE, | ||
| 'tenant_id': <>, | ||
| 'consuming_ptgs_details': [], | ||
| 'consuming_eps_details': [] | ||
| } | ||
|
|
||
| """ | ||
| nfp_create_nf_data = {} | ||
|
|
||
| sc_instance = context.instance | ||
| service_targets = self._get_service_targets(context) | ||
|
|
||
| consuming_ptgs_details, consuming_eps_details = \ | ||
| self._get_consumers_for_provider(context, | ||
| service_targets['provider_ptg'][0]) | ||
|
|
||
| if context.current_profile['service_type'] == pconst.LOADBALANCER: | ||
| config_param_values = sc_instance.get('config_param_values', {}) | ||
| if config_param_values: | ||
|
|
@@ -661,35 +758,58 @@ def _create_network_function(self, context): | |
| context.core_plugin.update_port( | ||
| context.plugin_context, provider_port['id'], port) | ||
|
|
||
| port_info = [] | ||
| if service_targets.get('provider_pts'): | ||
| # Device case, for Base mode ports won't be available. | ||
| port_info = [ | ||
| { | ||
| 'id': service_targets['provider_pts'][0], | ||
| 'port_model': nfp_constants.GBP_PORT, | ||
| 'port_classification': nfp_constants.PROVIDER, | ||
| } | ||
| ] | ||
| if service_targets.get('consumer_ports'): | ||
| port_info.append({ | ||
| 'id': service_targets['consumer_pts'][0], | ||
| 'port_model': nfp_constants.GBP_PORT, | ||
| 'port_classification': nfp_constants.CONSUMER, | ||
| }) | ||
| network_function = { | ||
| 'tenant_id': context.provider['tenant_id'], | ||
| 'service_chain_id': sc_instance['id'], | ||
| 'service_id': context.current_node['id'], | ||
| 'service_profile_id': context.current_profile['id'], | ||
| 'management_ptg_id': sc_instance['management_ptg_id'], | ||
| provider = { | ||
| 'pt': service_targets.get('provider_pt_objs', [None])[0], | ||
| 'ptg': service_targets.get('provider_ptg', [None])[0], | ||
| 'port': service_targets.get('provider_ports', [None])[0], | ||
| 'subnet': service_targets.get('provider_subnet', None), | ||
| 'port_model': nfp_constants.GBP_PORT, | ||
| 'port_classification': nfp_constants.PROVIDER} | ||
|
|
||
| consumer_pt = None | ||
| consumer_ptg = None | ||
| consumer_ports = None | ||
|
|
||
| if service_targets['consumer_pt_objs']: | ||
| consumer_pt = service_targets.get('consumer_pt_objs', [None])[0] | ||
| if service_targets['consumer_ptg']: | ||
| consumer_ptg = service_targets.get('consumer_ptg', [None])[0] | ||
| if service_targets['consumer_ports']: | ||
| consumer_ports = service_targets.get('consumer_ports', [None])[0] | ||
|
|
||
| consumer = { | ||
| 'pt': consumer_pt, | ||
| 'ptg': consumer_ptg, | ||
| 'port': consumer_ports, | ||
| 'subnet': service_targets.get('consumer_subnet', None), | ||
| 'port_model': nfp_constants.GBP_PORT, | ||
| 'port_classification': nfp_constants.CONSUMER} | ||
|
|
||
| management = { | ||
| 'pt': None, | ||
| 'ptg': None, | ||
| 'port': None, | ||
| 'subnet': None, | ||
| 'port_model': nfp_constants.GBP_NETWORK, | ||
| 'port_classification': nfp_constants.MANAGEMENT} | ||
|
|
||
| nfp_create_nf_data = { | ||
| 'resource_owner_context': context._plugin_context.to_dict(), | ||
| 'service_chain_instance': sc_instance, | ||
| 'service_chain_node': context.current_node, | ||
| 'service_profile': context.current_profile, | ||
| 'service_config': context.current_node.get('config'), | ||
| 'port_info': port_info, | ||
| 'provider': provider, | ||
| 'consumer': consumer, | ||
| 'management': management, | ||
| 'management_ptg_id': sc_instance['management_ptg_id'], | ||
| 'network_function_mode': nfp_constants.GBP_MODE, | ||
| } | ||
| 'tenant_id': context.provider['tenant_id'], | ||
| 'consuming_ptgs_details': consuming_ptgs_details, | ||
| 'consuming_eps_details': consuming_eps_details} | ||
|
|
||
| return self.nfp_notifier.create_network_function( | ||
| context.plugin_context, network_function=network_function)['id'] | ||
| context.plugin_context, network_function=nfp_create_nf_data)['id'] | ||
|
|
||
| def _set_node_instance_network_function_map( | ||
| self, session, sc_node_id, sc_instance_id, network_function_id): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| [DEFAULT] | ||
| workers=1 | ||
| workers=2 | ||
| debug=False | ||
| kombu_reconnect_delay=1.0 | ||
| rabbit_use_ssl=False | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,9 @@ | |
| from gbpservice.nfp.core import event as nfp_event | ||
| from gbpservice.nfp.core import poll as nfp_poll | ||
|
|
||
| STOP_POLLING = {'poll': False} | ||
| CONTINUE_POLLING = {'poll': True} | ||
|
|
||
| LOG = nfp_logging.getLogger(__name__) | ||
|
|
||
| """Implements APIs invoked by configurator for processing RPC messages. | ||
|
|
@@ -65,6 +68,7 @@ def _send_event(self, context, resource_data, event_id, event_key=None): | |
| arg_dict = {'context': context, | ||
| 'resource_data': resource_data} | ||
| ev = self.sc.new_event(id=event_id, data=arg_dict, key=event_key) | ||
|
|
||
| self.sc.post_event(ev) | ||
|
|
||
| def configure_interfaces(self, context, resource_data): | ||
|
|
@@ -268,8 +272,9 @@ def _process_event(self, ev): | |
| if (resource_data.get('periodicity') == gen_cfg_const.INITIAL and | ||
| result == common_const.SUCCESS): | ||
| notification_data = self._prepare_notification_data(ev, result) | ||
| self.sc.poll_event_done(ev) | ||
| # self.sc.poll_event_done(ev) | ||
| self.notify._notification(notification_data) | ||
| return STOP_POLLING | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Didn't get the difference between returning STOP_POLLING vs invoking poll_event_done. Is this functionality fix or perf?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. long time back "poll_event_done" was disabled, orchestrator moved to STOP_POLLING but configurator didnt. this change is not for perf. |
||
| elif resource_data.get('periodicity') == gen_cfg_const.FOREVER: | ||
| if result == common_const.FAILED: | ||
| """If health monitoring fails continuously for 5 times | ||
|
|
@@ -282,8 +287,9 @@ def _process_event(self, ev): | |
| notification_data = self._prepare_notification_data( | ||
| ev, | ||
| result) | ||
| self.sc.poll_event_done(ev) | ||
| # self.sc.poll_event_done(ev) | ||
| self.notify._notification(notification_data) | ||
| return STOP_POLLING | ||
| elif result == common_const.SUCCESS: | ||
| """set fail_count to 0 if it had failed earlier even once | ||
| """ | ||
|
|
@@ -293,8 +299,9 @@ def _process_event(self, ev): | |
| that particular service vm's health monitor | ||
| """ | ||
| notification_data = self._prepare_notification_data(ev, result) | ||
| self.sc.poll_event_done(ev) | ||
| # self.sc.poll_event_done(ev) | ||
| self.notify._notification(notification_data) | ||
| return STOP_POLLING | ||
| else: | ||
| """For other events, irrespective of result send notification""" | ||
| notification_data = self._prepare_notification_data(ev, result) | ||
|
|
@@ -357,7 +364,7 @@ def poll_event_cancel(self, ev): | |
|
|
||
| @nfp_poll.poll_event_desc( | ||
| event=gen_cfg_const.EVENT_CONFIGURE_HEALTHMONITOR, | ||
| spacing=5) | ||
| spacing=2) | ||
| def handle_configure_healthmonitor(self, ev): | ||
| """Decorator method called for poll event CONFIGURE_HEALTHMONITOR | ||
| Finally it Enqueues response into notification queue. | ||
|
|
@@ -367,7 +374,7 @@ def handle_configure_healthmonitor(self, ev): | |
| Returns: None | ||
|
|
||
| """ | ||
| self._process_event(ev) | ||
| return self._process_event(ev) | ||
|
|
||
|
|
||
| def events_init(sc, drivers, rpcmgr): | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use constants to define threadpool count.