def update_useras(testcase, user_as, att_confs: List[AttachmentConf], deleted_links: List[Link] = [], **kwargs): """ Update a `UserAS` and the configuration of its attachments """ prev_aps_isd = user_as.isd prev_cert_chain = user_as.certificates.latest(Certificate.CHAIN) hosts_pending_before = set(Host.objects.needs_config_deployment()) with patch.object(AttachmentPoint, 'trigger_deployment', autospec=True) as mock_deploy: user_as.update( label=kwargs.get('label', user_as.label), installation_type=kwargs.get('installation_type', user_as.installation_type), ) user_as.update_attachments(att_confs, deleted_links) # Check that deployment was triggered strictly once for each attachment point testcase.assertEqual( len([args[0] for args, kwargs in mock_deploy.call_args_list]), len(set(args[0] for args, kwargs in mock_deploy.call_args_list))) # Check that deployment was triggered for all the attachment points testcase.assertEqual( set(args[0] for args, kwargs in mock_deploy.call_args_list), set(AttachmentConf.attachment_points(att_confs)) | set([ link.interfaceA.AS.attachment_point_info for link in deleted_links ])) # Check needs_config_deployment: hosts of UserAS and both APs aps_hosts = flatten(ap.AS.hosts.all() for ap in AttachmentConf.attachment_points(att_confs)) testcase.assertSetEqual( hosts_pending_before | set(user_as.hosts.all()) | set(aps_hosts), set(Host.objects.needs_config_deployment())) # Check certificates reset if ISD changed curr_aps_isd = user_as.isd cert_chain = user_as.certificates.latest(Certificate.CHAIN) if prev_aps_isd != curr_aps_isd: testcase.assertEqual( cert_chain.version, prev_cert_chain.version + 1, ("Certificate needs to be recreated on ISD change: " "ISD before: %s, ISD after:%s" % (prev_aps_isd, curr_aps_isd))) testcase.assertEqual( user_as.certificates.filter(type=Certificate.CHAIN).count(), 1) else: testcase.assertEqual(prev_cert_chain, cert_chain) utils.check_topology(testcase)
def user_as_delete_ap(self): seed = 4 r = random.Random(seed) as_ids = r.choice(get_random_as_ids_combinations()) user_as, att_confs = create_and_check_random_useras( self, seed, as_ids, VPNChoice.ALL, wants_user_ap=True, public_ip=test_public_ip) test_att_confs_user_as = AttachmentConf( attachment_point=user_as.attachment_point_info, public_ip=test_public_ip, public_port=55555) create_and_check_random_useras( self, seed, as_ids, VPNChoice.ALL, kwargs={"att_confs": test_att_confs_user_as}) update_useras(self, user_as, att_confs, wants_user_ap=False, public_ip="") check_random_useras(self, seed, user_as, att_confs, VPNChoice.ALL, wants_user_ap=False, public_ip="")
def create_user_as(ap, label='Some label'): user_as = UserAS.objects.create( owner=get_testuser(), installation_type=UserAS.VM, isd=ap.AS.isd, label=label, ) att_conf = AttachmentConf(ap, use_vpn=True, public_port=test_public_port) user_as.update_attachments([att_conf]) return user_as
def _get_random_att_confs(seed, as_ids: List[ASdef], vpn_choice: VPNChoice, force_public_ip=False, force_bind_ip=False, **kwargs) -> List[AttachmentConf]: """ Generate random compatible `AttachmentConf`s for the given `ASdef`s based on `seed`. """ r = random.Random(seed) att_confs = [] used_public_ip_port_pairs = set() used_bind_ip_port_pairs = set() attachment_points = aps_from_ids(as_ids) for ap in attachment_points: att_conf_dict = {} att_conf_dict['attachment_point'] = ap if vpn_choice in (VPNChoice.NONE, VPNChoice.ALL): att_conf_dict[ 'use_vpn'] = False if vpn_choice is VPNChoice.NONE else True else: if not ap.vpn: att_conf_dict['use_vpn'] = False else: att_conf_dict['use_vpn'] = _randbool(r) while True: public_ip = '172.31.0.%i' % r.randint(10, 254) public_port = r.choice( range(DEFAULT_PUBLIC_PORT, DEFAULT_PUBLIC_PORT + 20)) if (public_ip, public_port) not in used_public_ip_port_pairs: used_public_ip_port_pairs.add((public_ip, public_port)) break if _randbool( r) or att_conf_dict['use_vpn'] is False or force_public_ip: att_conf_dict['public_ip'] = public_ip else: att_conf_dict['public_ip'] = None att_conf_dict['public_port'] = public_port while True: bind_ip = '192.168.1.%i' % r.randint(10, 254) bind_port = r.choice( range(DEFAULT_PUBLIC_PORT + 1000, DEFAULT_PUBLIC_PORT + 1020)) if (bind_ip, bind_port) not in used_bind_ip_port_pairs: used_bind_ip_port_pairs.add((bind_ip, bind_port)) break if _randbool(r) or force_bind_ip: att_conf_dict['bind_ip'] = bind_ip att_conf_dict['bind_port'] = bind_port else: att_conf_dict['bind_ip'] = None att_conf_dict['bind_port'] = None att_confs.append(AttachmentConf(**att_conf_dict)) return att_confs
def _create_user_as(owner, attachment_point, installation_type, use_vpn): user_as = UserAS.objects.create(owner=owner, installation_type=installation_type, label="", isd=attachment_point.AS.isd) user_as.update_attachments([ AttachmentConf(attachment_point=attachment_point, use_vpn=use_vpn, public_ip='172.31.0.200', public_port=54321, bind_ip=None, bind_port=None) ])
def save(self, commit=True, user_as=None): """ :return AttachmentPointConf: """ assert not commit, "Persistency in the DB shall be handled in the save(...) method of the \ AttachmentLinksFormSet" return AttachmentConf(self.cleaned_data['attachment_point'], self.cleaned_data['public_ip'] or None, # Interface needs None not '' self.cleaned_data['public_port'], self.cleaned_data['bind_ip'] or None, self.cleaned_data['bind_port'], self.cleaned_data['use_vpn'], self.cleaned_data['active'], self.instance if self.instance.pk is not None else None)
def _create_ases_for_testuser(num): """ Create a number `num` UserASes for testuser """ user = get_testuser() num_existing_ases = UserAS.objects.filter(owner=user).count() for i in range(num_existing_ases, num_existing_ases + num): ap = AttachmentPoint.objects.first() user_as = UserAS.objects.create( owner=user, installation_type=UserAS.VM, isd=ap.AS.isd, label="Testuser's AS number %i" % (i + 1), ) att_conf = AttachmentConf(ap, public_ip=_test_ip, public_port=_test_start_port + i) user_as.update_attachments([att_conf])
def update_useras(testcase, user_as, att_confs: List[AttachmentConf], deleted_links: List[Link] = [], wants_user_ap=False, public_ip="", wants_vpn=False, **kwargs): """ Update a `UserAS` and the configuration of its attachments """ prev_aps_isd = user_as.isd prev_cert_chain = Certificate.objects.latest(Key.CP_AS, user_as) hosts_pending_before = set(Host.objects.needs_config_deployment()) user_as.update( label=kwargs.get('label', user_as.label), installation_type=kwargs.get('installation_type', user_as.installation_type), public_ip=public_ip, wants_user_ap=wants_user_ap, wants_vpn=wants_vpn, ) user_as.update_attachments(att_confs, deleted_links) # Check needs_config_deployment: hosts of UserAS and both APs aps_hosts = flatten(ap.AS.hosts.all() for ap in AttachmentConf.attachment_points(att_confs)) testcase.assertSetEqual( hosts_pending_before | set(user_as.hosts.all()) | set(aps_hosts), set(Host.objects.needs_config_deployment())) # Check certificates reset if ISD changed curr_aps_isd = user_as.isd cert_chain = Certificate.objects.latest(Key.CP_AS, user_as) if prev_aps_isd != curr_aps_isd: testcase.assertEqual( cert_chain.version, prev_cert_chain.version + 1, ("Certificate needs to be recreated on ISD change: " "ISD before: %s, ISD after:%s" % (prev_aps_isd, curr_aps_isd))) testcase.assertEqual( user_as.certificates().filter(key__usage=Key.CP_AS).count(), 1) else: testcase.assertEqual(prev_cert_chain, cert_chain) utils.check_topology(testcase)
def _create_user_as(attachment_point, label="Some label"): """ Create a UserAS in a transaction, as would happen in a view. This will then trigger the on_commit and run the deployment tasks. :returns UserAS: the created user_as """ user_as = UserAS.objects.create( owner=get_testuser(), installation_type=UserAS.PKG, isd=attachment_point.AS.isd, label=label, ) att_conf = AttachmentConf(attachment_point, str(ipaddress.ip_address(test_public_ip) + 2), test_public_port, bind_ip=None, bind_port=None, use_vpn=False) user_as.update_attachments([att_conf]) return user_as