mirror of
				https://github.com/peeringdb/peeringdb.git
				synced 2024-05-11 05:55:09 +00:00 
			
		
		
		
	* stub in poetry for pipenv * re-add tester image * add pre-commit / formatting * fix ghactions * revert test data whitespace, exclude tests/data * revert ws * decruft, rm tox/pipenv * install dev packages for base image * add lgtm config to force to py3
		
			
				
	
	
		
			167 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import re
 | |
| 
 | |
| import reversion
 | |
| from django.core.management.base import BaseCommand, CommandError
 | |
| 
 | |
| import peeringdb_server.models as pdbm
 | |
| from peeringdb_server.mail import mail_users_entity_merge
 | |
| 
 | |
| 
 | |
| def soft_delete(fac, cmd):
 | |
|     # overriding
 | |
| 
 | |
|     for k in fac._handleref.delete_cascade:
 | |
|         q = getattr(fac, k).exclude(status="deleted")
 | |
|         for c in q:
 | |
|             if c not in cmd.moved:
 | |
|                 soft_delete(c, cmd)
 | |
| 
 | |
|     cmd.log("soft deleting %s" % fac)
 | |
|     if cmd.commit:
 | |
|         fac.status = "deleted"
 | |
|         fac.save()
 | |
| 
 | |
| 
 | |
| class Command(BaseCommand):
 | |
|     help = "merge facilities"
 | |
|     pretend = False
 | |
| 
 | |
|     def add_arguments(self, parser):
 | |
|         parser.add_argument(
 | |
|             "--commit", action="store_true", help="will commit the fac merge"
 | |
|         )
 | |
|         parser.add_argument("--target", help="target of the merge (facility id)")
 | |
|         parser.add_argument("--ids", help="comma separated list of facility ids")
 | |
|         parser.add_argument(
 | |
|             "--match", help="all facs with matching names will be merged (regex)"
 | |
|         )
 | |
| 
 | |
|     def log(self, msg):
 | |
|         if not self.commit:
 | |
|             self.stdout.write("%s [pretend]" % msg)
 | |
|         else:
 | |
|             self.stdout.write(msg)
 | |
| 
 | |
|     @reversion.create_revision()
 | |
|     def handle(self, *args, **options):
 | |
|         self.commit = options.get("commit", False)
 | |
|         self.moved = []
 | |
| 
 | |
|         self.target = options.get("target", 0)
 | |
|         if not self.target:
 | |
|             msg = "Target ID required (--target)"
 | |
|             self.log(msg)
 | |
|             raise CommandError(msg)
 | |
| 
 | |
|         self.match = options.get("match", None)
 | |
|         self.ids = options.get("ids", "")
 | |
| 
 | |
|         facs = []
 | |
|         moved = self.moved
 | |
| 
 | |
|         if self.match:
 | |
|             if self.ids:
 | |
|                 msg = "ids and match are mutually exclusive"
 | |
|                 self.log(msg)
 | |
|                 raise CommandError(msg)
 | |
| 
 | |
|             self.log("Merging all facilities matching '%s'" % self.match)
 | |
|             for fac in pdbm.Facility.objects.exclude(status="deleted"):
 | |
|                 if re.match(self.match, fac.name, re.IGNORECASE):
 | |
|                     facs.append(fac)
 | |
| 
 | |
|         elif self.ids:
 | |
|             self.ids = self.ids.split(",")
 | |
|             self.log(
 | |
|                 "Merging facilities {} -> {}".format(", ".join(self.ids), self.target)
 | |
|             )
 | |
|             for fac in pdbm.Facility.objects.filter(id__in=self.ids):
 | |
|                 facs.append(fac)
 | |
| 
 | |
|         else:
 | |
|             msg = "IDs or match is required"
 | |
|             self.log(msg)
 | |
|             raise CommandError(msg)
 | |
| 
 | |
|         self.target = pdbm.Facility.objects.get(id=self.target)
 | |
| 
 | |
|         if self.target.status == "deleted":
 | |
|             self.target.status = "ok"
 | |
|             if self.commit:
 | |
|                 self.target.save()
 | |
| 
 | |
|         for fac in facs:
 | |
|             if fac.id == self.target.id:
 | |
|                 continue
 | |
|             self.log("Merging %s (%d) .." % (fac, fac.id))
 | |
|             for netfac in pdbm.NetworkFacility.objects.filter(facility=fac).exclude(
 | |
|                 status="deleted"
 | |
|             ):
 | |
|                 netfac_other = pdbm.NetworkFacility.objects.filter(
 | |
|                     facility=self.target, network_id=netfac.network_id
 | |
|                 )
 | |
|                 # we check if the target fac already has a netfac to the same network (that is currently undeleted), if it does we skip it
 | |
|                 if netfac_other.exclude(status="deleted").exists():
 | |
|                     self.log(
 | |
|                         "  - netfac %s : connection already exists at target, skipping."
 | |
|                         % netfac
 | |
|                     )
 | |
|                     continue
 | |
|                 # if it exists but is currently delete, we simply undelete it
 | |
|                 elif netfac_other.exists():
 | |
|                     netfac_other = netfac_other.first()
 | |
|                     netfac_other.local_asn = netfac.local_asn
 | |
|                     netfac_other.avail_sonet = netfac.avail_sonet
 | |
|                     netfac_other.avail_ethernet = netfac.avail_ethernet
 | |
|                     netfac_other.avail_atm = netfac.avail_atm
 | |
|                     netfac_other.status = "ok"
 | |
|                     self.log("  - netfac %s (undeleting and updating)" % netfac_other)
 | |
|                     moved.append(netfac_other)
 | |
|                     if self.commit:
 | |
|                         netfac_other.save()
 | |
|                 # if it doesnt exist, we update the facility to the target facility and save
 | |
|                 else:
 | |
|                     self.log("  - netfac %s" % netfac)
 | |
|                     netfac.facility = self.target
 | |
|                     moved.append(netfac)
 | |
|                     if self.commit:
 | |
|                         netfac.save()
 | |
| 
 | |
|             for ixfac in pdbm.InternetExchangeFacility.objects.filter(
 | |
|                 facility=fac
 | |
|             ).exclude(status="deleted"):
 | |
|                 ixfac_other = pdbm.InternetExchangeFacility.objects.filter(
 | |
|                     facility=self.target, ix=ixfac.ix
 | |
|                 )
 | |
|                 # we check if the target fac already has an ixfac to the same exchange (that is currently undeleted), if it does, we skip it
 | |
|                 if ixfac_other.exclude(status="deleted").exists():
 | |
|                     self.log(
 | |
|                         "  - ixfac %s : connection already exists at target, skipping."
 | |
|                         % ixfac
 | |
|                     )
 | |
|                     continue
 | |
|                 # if it exists but is currently deleted, we undelete and copy
 | |
|                 elif ixfac_other.exists():
 | |
|                     ixfac_other = ixfac_other.first()
 | |
|                     ixfac_other.status = "ok"
 | |
|                     moved.append(ixfac_other)
 | |
|                     self.log("  - ixfac %s (undeleting and updating)" % ixfac_other)
 | |
|                     if self.commit:
 | |
|                         ixfac_other.save()
 | |
|                 # if it doesnt exist, we update the facility to the target facility and save
 | |
|                 else:
 | |
|                     self.log("  - ixfac %s" % ixfac)
 | |
|                     ixfac.facility = self.target
 | |
|                     moved.append(ixfac)
 | |
|                     if self.commit:
 | |
|                         ixfac.save()
 | |
| 
 | |
|             soft_delete(fac, self)
 | |
|             if self.commit:
 | |
|                 mail_users_entity_merge(
 | |
|                     fac.org.admin_usergroup.user_set.all(),
 | |
|                     self.target.org.admin_usergroup.user_set.all(),
 | |
|                     fac,
 | |
|                     self.target,
 | |
|                 )
 |