Merge "Implement the 'gbp purge <tenant ID>' CLI" into stable/mitaka
This commit is contained in:
		
							
								
								
									
										112
									
								
								gbpclient/gbp/v2_0/purge.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								gbpclient/gbp/v2_0/purge.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					#    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.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from neutronclient.common import exceptions as nexc
 | 
				
			||||||
 | 
					from neutronclient.neutron.v2_0 import purge as n_purge
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AUTO_PTG_REGEX = 'auto[0-9a-f]{32}\Z'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Purge(n_purge.Purge):
 | 
				
			||||||
 | 
					    """Delete all resources that belong to a given tenant."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _pluralize(self, string):
 | 
				
			||||||
 | 
					        if re.search('_policy$', string):
 | 
				
			||||||
 | 
					            return re.sub('_policy$', '_policies', string)
 | 
				
			||||||
 | 
					        return string + 's'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _get_resources(self, neutron_client, resource_types, tenant_id):
 | 
				
			||||||
 | 
					        resources = super(Purge, self)._get_resources(neutron_client,
 | 
				
			||||||
 | 
					                                                      resource_types,
 | 
				
			||||||
 | 
					                                                      tenant_id)
 | 
				
			||||||
 | 
					        # exclude auto_ptg as it was created by implicit workflow
 | 
				
			||||||
 | 
					        if 'policy_target_group' in resource_types:
 | 
				
			||||||
 | 
					            index = resource_types.index('policy_target_group')
 | 
				
			||||||
 | 
					            for resource in list(resources[index]):
 | 
				
			||||||
 | 
					                if re.match(AUTO_PTG_REGEX, resource['id']):
 | 
				
			||||||
 | 
					                    resources[index].remove(resource)
 | 
				
			||||||
 | 
					                    self.total_resources -= 1
 | 
				
			||||||
 | 
					        return resources
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _purge_resources(self, neutron_client, resource_types,
 | 
				
			||||||
 | 
					                         tenant_resources):
 | 
				
			||||||
 | 
					        deleted = {}
 | 
				
			||||||
 | 
					        failed = {}
 | 
				
			||||||
 | 
					        failures = False
 | 
				
			||||||
 | 
					        for index, resources in enumerate(tenant_resources):
 | 
				
			||||||
 | 
					            resource_type = resource_types[index]
 | 
				
			||||||
 | 
					            failed[resource_type] = 0
 | 
				
			||||||
 | 
					            deleted[resource_type] = 0
 | 
				
			||||||
 | 
					            for resource in resources:
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    self._delete_resource(neutron_client, resource_type,
 | 
				
			||||||
 | 
					                                          resource)
 | 
				
			||||||
 | 
					                    deleted[resource_type] += 1
 | 
				
			||||||
 | 
					                    self.deleted_resources += 1
 | 
				
			||||||
 | 
					                except nexc.NotFound:
 | 
				
			||||||
 | 
					                    # this is for l2p/l3p created under the
 | 
				
			||||||
 | 
					                    # implicit workflow.
 | 
				
			||||||
 | 
					                    deleted[resource_type] += 1
 | 
				
			||||||
 | 
					                    self.deleted_resources += 1
 | 
				
			||||||
 | 
					                except Exception:
 | 
				
			||||||
 | 
					                    failures = True
 | 
				
			||||||
 | 
					                    failed[resource_type] += 1
 | 
				
			||||||
 | 
					                    self.total_resources -= 1
 | 
				
			||||||
 | 
					                percent_complete = 100
 | 
				
			||||||
 | 
					                if self.total_resources > 0:
 | 
				
			||||||
 | 
					                    percent_complete = (self.deleted_resources /
 | 
				
			||||||
 | 
					                                        float(self.total_resources)) * 100
 | 
				
			||||||
 | 
					                sys.stdout.write("\rPurging resources: %d%% complete." %
 | 
				
			||||||
 | 
					                                 percent_complete)
 | 
				
			||||||
 | 
					                sys.stdout.flush()
 | 
				
			||||||
 | 
					        return (deleted, failed, failures)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def take_action(self, parsed_args):
 | 
				
			||||||
 | 
					        neutron_client = self.get_client()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.any_failures = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # A list of the types of resources supported in the order in which
 | 
				
			||||||
 | 
					        # they should be deleted.
 | 
				
			||||||
 | 
					        resource_types = ['policy_target', 'policy_target_group', 'l2_policy',
 | 
				
			||||||
 | 
					                          'l3_policy', 'external_policy', 'nat_pool',
 | 
				
			||||||
 | 
					                          'external_segment', 'policy_rule_set',
 | 
				
			||||||
 | 
					                          'policy_rule', 'policy_classifier',
 | 
				
			||||||
 | 
					                          'policy_action', 'network_service_policy',
 | 
				
			||||||
 | 
					                          'servicechain_instance', 'servicechain_spec',
 | 
				
			||||||
 | 
					                          'servicechain_node', 'service_profile']
 | 
				
			||||||
 | 
					        deleted = {}
 | 
				
			||||||
 | 
					        failed = {}
 | 
				
			||||||
 | 
					        self.total_resources = 0
 | 
				
			||||||
 | 
					        self.deleted_resources = 0
 | 
				
			||||||
 | 
					        resources = self._get_resources(neutron_client, resource_types,
 | 
				
			||||||
 | 
					                                        parsed_args.tenant)
 | 
				
			||||||
 | 
					        deleted, failed, failures = self._purge_resources(neutron_client,
 | 
				
			||||||
 | 
					                                                          resource_types,
 | 
				
			||||||
 | 
					                                                          resources)
 | 
				
			||||||
 | 
					        print('\n%s' % self._build_message(deleted, failed, failures))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO(Kent): clean up Neutron resources also
 | 
				
			||||||
 | 
					        # super(Purge, self).take_action(parsed_args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PurgeAPI(Purge):
 | 
				
			||||||
 | 
					    def __init__(self, app, app_args, gbp_client):
 | 
				
			||||||
 | 
					        self.gbp_client = gbp_client
 | 
				
			||||||
 | 
					        super(PurgeAPI, self).__init__(app, app_args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_client(self):
 | 
				
			||||||
 | 
					        return self.gbp_client
 | 
				
			||||||
@@ -39,6 +39,7 @@ from neutronclient.i18n import _
 | 
				
			|||||||
from neutronclient.version import __version__
 | 
					from neutronclient.version import __version__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from gbpclient.gbp.v2_0 import groupbasedpolicy as gbp
 | 
					from gbpclient.gbp.v2_0 import groupbasedpolicy as gbp
 | 
				
			||||||
 | 
					from gbpclient.gbp.v2_0 import purge
 | 
				
			||||||
from gbpclient.gbp.v2_0 import servicechain
 | 
					from gbpclient.gbp.v2_0 import servicechain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VERSION = '2.0'
 | 
					VERSION = '2.0'
 | 
				
			||||||
@@ -157,6 +158,7 @@ COMMAND_V2 = {
 | 
				
			|||||||
    'policy-rule-set-update': gbp.UpdatePolicyRuleSet,
 | 
					    'policy-rule-set-update': gbp.UpdatePolicyRuleSet,
 | 
				
			||||||
    'policy-rule-set-list': gbp.ListPolicyRuleSet,
 | 
					    'policy-rule-set-list': gbp.ListPolicyRuleSet,
 | 
				
			||||||
    'policy-rule-set-show': gbp.ShowPolicyRuleSet,
 | 
					    'policy-rule-set-show': gbp.ShowPolicyRuleSet,
 | 
				
			||||||
 | 
					    'purge': purge.Purge,
 | 
				
			||||||
    'service-profile-list': servicechain.ListServiceProfile,
 | 
					    'service-profile-list': servicechain.ListServiceProfile,
 | 
				
			||||||
    'service-profile-show': servicechain.ShowServiceProfile,
 | 
					    'service-profile-show': servicechain.ShowServiceProfile,
 | 
				
			||||||
    'service-profile-create': servicechain.CreateServiceProfile,
 | 
					    'service-profile-create': servicechain.CreateServiceProfile,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								gbpclient/tests/unit/test_cli20_purge.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								gbpclient/tests/unit/test_cli20_purge.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					#    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 neutronclient.tests.unit import test_cli20_purge
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CLITestV20Purge(test_cli20_purge.CLITestV20Purge):
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        super(CLITestV20Purge, self).setUp()
 | 
				
			||||||
 | 
					        self.resource_types = ['policy_target', 'policy_target_group',
 | 
				
			||||||
 | 
					                               'l2_policy', 'l3_policy', 'external_policy',
 | 
				
			||||||
 | 
					                               'nat_pool', 'external_segment',
 | 
				
			||||||
 | 
					                               'policy_rule_set', 'policy_rule',
 | 
				
			||||||
 | 
					                               'policy_classifier', 'policy_action',
 | 
				
			||||||
 | 
					                               'network_service_policy',
 | 
				
			||||||
 | 
					                               'servicechain_instance', 'servicechain_spec',
 | 
				
			||||||
 | 
					                               'servicechain_node', 'service_profile']
 | 
				
			||||||
@@ -14,6 +14,7 @@
 | 
				
			|||||||
import logging
 | 
					import logging
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from gbpclient.gbp.v2_0 import purge as gbpclient_purge
 | 
				
			||||||
from neutronclient import client
 | 
					from neutronclient import client
 | 
				
			||||||
from neutronclient.common import exceptions
 | 
					from neutronclient.common import exceptions
 | 
				
			||||||
from neutronclient.common import serializer
 | 
					from neutronclient.common import serializer
 | 
				
			||||||
@@ -722,6 +723,10 @@ class Client(object):
 | 
				
			|||||||
        return self.delete(self.servicechain_instance_path %
 | 
					        return self.delete(self.servicechain_instance_path %
 | 
				
			||||||
                           (servicechain_instance))
 | 
					                           (servicechain_instance))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def purge(self, tenant_id):
 | 
				
			||||||
 | 
					        purge_obj = gbpclient_purge.PurgeAPI(None, None, self)
 | 
				
			||||||
 | 
					        purge_obj.take_action(tenant_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, **kwargs):
 | 
					    def __init__(self, **kwargs):
 | 
				
			||||||
        """Initialize a new client for the GBP v2.0 API."""
 | 
					        """Initialize a new client for the GBP v2.0 API."""
 | 
				
			||||||
        super(Client, self).__init__()
 | 
					        super(Client, self).__init__()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user