def save(self, user): """ Completes node registration. """ ip = self.cleaned_data.get('ip') project = self.cleaned_data.get('project') pool = self.cleaned_data.get('pool') prefix_len = self.cleaned_data.get('prefix_len') if prefix_len == 0: prefix_len = None subnet = None if not ip: # Assign a new IP address from the selected pool (if no IP address selected) node = Node() fresh_subnet = pool.allocate_subnet(prefix_len) net = ipcalc.Network(fresh_subnet.network, fresh_subnet.cidr) node.ip = str(net.host_first()) # Create a new subnet for this node or use an existing one if available subnet = Subnet(node = node, subnet = fresh_subnet.network, cidr = fresh_subnet.cidr) subnet.allocated = True subnet.allocated_at = datetime.now() subnet.status = SubnetStatus.NotAnnounced else: # When prefix is not available we should use /32 if prefix_len is None: prefix_len = 32 net = ipcalc.Network(ip, prefix_len) sub_ip = str(net.network()) # Check if this node already exists try: node = Node.objects.get(ip = str(net.host_first())) except Node.DoesNotExist: node = Node(ip = str(net.host_first())) # Reserve existing IP in the pool pool.reserve_subnet(sub_ip, prefix_len) try: subnet = Subnet.objects.get(node = node, subnet = sub_ip, cidr = prefix_len) subnet.status = SubnetStatus.AnnouncedOk except Subnet.DoesNotExist: subnet = Subnet(node = node, subnet = sub_ip, cidr = prefix_len) subnet.status = SubnetStatus.NotAnnounced subnet.allocated = True subnet.allocated_at = datetime.now() # Update node metadata node.name = self.cleaned_data.get('name').lower() node.project = project node.owner = user node.location = self.cleaned_data.get('location') node.geo_lat = self.cleaned_data.get('geo_lat') node.geo_long = self.cleaned_data.get('geo_long') node.ant_external = self.cleaned_data.get('ant_external') node.ant_polarization = self.cleaned_data.get('ant_polarization') node.ant_type = self.cleaned_data.get('ant_type') node.node_type = self.cleaned_data.get('node_type') node.notes = self.cleaned_data.get('notes') node.url = self.cleaned_data.get('url') node.redundancy_req = self.cleaned_data.get('redundancy_req') node.warnings = False for i in xrange(10): try: mac = gen_mac_address() Node.objects.get(vpn_mac_conf = mac) except Node.DoesNotExist: node.vpn_mac_conf = mac break else: raise Exception, "unable to generate unique MAC" if user.is_staff: node.system_node = self.cleaned_data.get('system_node') node.vpn_server = self.cleaned_data.get('vpn_server') if user.is_staff or getattr(settings, 'NONSTAFF_BORDER_ROUTERS', False): node.border_router = self.cleaned_data.get('border_router') node.status = NodeStatus.New node.save() # Create node traffic control policy tc_ingress = self.cleaned_data.get('tc_ingress') if tc_ingress: Policy.set_policy(node, node.vpn_mac_conf, PolicyAction.Shape, tc_ingress, PolicyFamily.Ethernet) # Create node profile for image generator if self.cleaned_data.get('template'): profile = Profile(node = node, template = self.cleaned_data.get('template')) if self.cleaned_data.get('channel') in ('', "0", None): profile.channel = node.project.channel else: profile.channel = self.cleaned_data.get('channel') profile.root_pass = self.cleaned_data.get('root_pass') profile.use_vpn = self.cleaned_data.get('use_vpn') profile.antenna = self.cleaned_data.get('ant_conn') or 0 profile.lan_bridge = self.cleaned_data.get('lan_bridge') or False profile.wan_dhcp = self.cleaned_data.get('wan_dhcp') profile.wan_ip = self.cleaned_data.get('wan_ip') profile.wan_cidr = self.cleaned_data.get('wan_cidr') profile.wan_gw = self.cleaned_data.get('wan_gw') if self.cleaned_data.get('tc_egress'): profile.vpn_egress_limit = self.cleaned_data.get('tc_egress').bandwidth profile.save() profile.optional_packages = self.cleaned_data.get('optional_packages') profile.save() if subnet: subnet.node = node subnet.save() # Update DNS entries Record.update_for_node(node) # Registers node name NodeNames(name = node.name, node = node).save() # Generate node added event Event.create_event(node, EventCode.NodeAdded, '', EventSource.NodeDatabase, data = 'Maintainer: %s' % node.owner.username) self.node = node return node
def save(self, node, user): """ Completes node data update. """ self.requires_firmware_update = False ip = self.cleaned_data.get('ip') oldName = node.name oldProject = node.project # Update node metadata node.name = self.cleaned_data.get('name').lower() node.owner = self.cleaned_data.get('owner') node.location = self.cleaned_data.get('location') node.geo_lat = self.cleaned_data.get('geo_lat') node.geo_long = self.cleaned_data.get('geo_long') node.ant_external = self.cleaned_data.get('ant_external') node.ant_polarization = self.cleaned_data.get('ant_polarization') node.ant_type = self.cleaned_data.get('ant_type') node.project = self.cleaned_data.get('project') node.node_type = self.cleaned_data.get('node_type') node.notes = self.cleaned_data.get('notes') node.url = self.cleaned_data.get('url') node.redundancy_req = self.cleaned_data.get('redundancy_req') if user.is_staff: node.system_node = self.cleaned_data.get('system_node') node.vpn_server = self.cleaned_data.get('vpn_server') if user.is_staff or getattr(settings, 'NONSTAFF_BORDER_ROUTERS', False): node.border_router = self.cleaned_data.get('border_router') node.save() # Update node traffic control policy tc_ingress = self.cleaned_data.get('tc_ingress') if tc_ingress: Policy.set_policy(node, node.vpn_mac_conf, PolicyAction.Shape, tc_ingress, PolicyFamily.Ethernet) else: try: node.gw_policy.get(addr = node.vpn_mac_conf, family = PolicyFamily.Ethernet).delete() except Policy.DoesNotExist: pass # Update DNS records on name changes if oldName != node.name or oldProject != node.project: Record.update_for_node(node, old_name = oldName, old_project = oldProject) # Generate node renamed event if oldName != node.name: Event.create_event(node, EventCode.NodeRenamed, '', EventSource.NodeDatabase, data = 'Old name: %s\n New name: %s' % (oldName, node.name)) # Update node profile for image generator try: profile = node.profile except Profile.DoesNotExist: profile = None if self.cleaned_data.get('template'): if not profile: profile = Profile(node = node, template = self.cleaned_data.get('template')) # Handle potential hardware changes new_template = self.cleaned_data.get('template') if profile.template != new_template: # Rename traffic graphs to preserve history node.rename_graphs(GraphType.Traffic, profile.template.iface_wifi, new_template.iface_wifi) def set_and_check(**kwargs): for key, value in kwargs.iteritems(): field = getattr(profile, key) meta = profile._meta.get_field(key) prep = meta.get_db_prep_value(value, connection) if isinstance(meta, models.ManyToManyField): if set([m.pk for m in field.all()]) != set([m.pk for m in value]): self.requires_firmware_update = True elif field != prep: self.requires_firmware_update = True setattr(profile, key, value) if not self.cleaned_data.get('channel'): set_and_check(channel = node.project.channel) else: set_and_check(channel = self.cleaned_data.get('channel')) set_and_check( template = self.cleaned_data.get('template'), root_pass = self.cleaned_data.get('root_pass'), use_vpn = self.cleaned_data.get('use_vpn'), antenna = self.cleaned_data.get('ant_conn') or 0, lan_bridge = self.cleaned_data.get('lan_bridge') or False, wan_dhcp = self.cleaned_data.get('wan_dhcp'), wan_ip = self.cleaned_data.get('wan_ip'), wan_cidr = self.cleaned_data.get('wan_cidr'), wan_gw = self.cleaned_data.get('wan_gw') ) if self.cleaned_data.get('tc_egress'): set_and_check(vpn_egress_limit = self.cleaned_data.get('tc_egress').bandwidth) else: set_and_check(vpn_egress_limit = None) profile.save() set_and_check(optional_packages = self.cleaned_data.get('optional_packages')) profile.save() elif profile and (settings.IMAGE_GENERATOR_ENABLED or settings.DEBUG): profile.delete() # Registers node name NodeNames(name = node.name, node = node).save() return node
def save(self): """ Performs the actual renumbering. """ # We must ensure exclusive access during node updates as otherwise this might happen # in the middle of a monitor update and this would cause unwanted consequences self.__node.ensure_exclusive_access() # Determine what subnet primary IP belonged to primary = self.__node.get_primary_subnet() renumber_primary = False old_router_id = self.__node.ip # Renumber subnets first for subnet in queryset_by_ip(self.__node.subnet_set.filter(allocated = True), 'ip_subnet')[:]: action = int(self.cleaned_data.get('subnet_%s' % subnet.pk)) prefix_len = int(self.cleaned_data.get('prefix_%s' % subnet.pk) or 27) manual_ip = self.cleaned_data.get('manual_%s' % subnet.pk) if action == RenumberAction.Keep: pass elif action == RenumberAction.Remove: subnet.delete() else: # This means we should renumber to some other pool pool = Pool.objects.get(pk = action) if manual_ip: new_subnet = pool.reserve_subnet(manual_ip, prefix_len) else: new_subnet = pool.allocate_subnet(prefix_len) # If the old subnet has been the source of node's primary IP remember that save_primary = (not renumber_primary and primary and primary[0] == subnet) # Remove old subnet and create a new one; it is deleted here so the old allocation # is returned to the pool and all status info is reset subnet.delete() s = Subnet(node = self.__node, subnet = new_subnet.network, cidr = new_subnet.cidr) s.allocated = True s.allocated_at = datetime.now() s.status = SubnetStatus.NotAnnounced s.description = subnet.description s.gen_iface_type = subnet.gen_iface_type s.gen_dhcp = subnet.gen_dhcp s.save() if save_primary: primary = s renumber_primary = True # The subnet have now been renumbered, check if we need to renumber the primary IP router_id_changed = False if renumber_primary: net = ipcalc.Network(primary.subnet, primary.cidr) self.__node.ip = str(net.host_first()) router_id_changed = True # Remove conflicting invalid nodes (another node with the IP we just renumbered to) existing_nodes = Node.objects.filter(ip = self.__node.ip, status = NodeStatus.Invalid) if existing_nodes.count() > 0: self.warning_or_continue(_("There is an existing but unregistered node with the same primary IP address you are currently renumbering to! If you continue with this operation, this invalid node will be replaced.")) existing_nodes.delete() # Node has been renumbered, reset monitoring status as this node is obviously not # visible right after renumbering. if router_id_changed: # Update node's DNS record Record.update_for_node(self.__node) if not self.__node.is_pending(): self.__node.status = NodeStatus.Down self.__node.peers = 0 Link.objects.filter(src = self.__node).delete() Link.objects.filter(dst = self.__node).delete() self.__node.subnet_set.filter(allocated = False).delete() self.__node.subnet_set.all().update(status = SubnetStatus.NotAnnounced) # Setup a node renumbered notice (if one doesn't exist yet) try: notice = RenumberNotice.objects.get(node = self.__node) if notice.original_ip == self.__node.ip: notice.delete() self.__node.awaiting_renumber = False else: self.__node.awaiting_renumber = True except RenumberNotice.DoesNotExist: notice = RenumberNotice(node = self.__node) notice.original_ip = old_router_id notice.renumbered_at = datetime.now() notice.save() self.__node.awaiting_renumber = True self.__node.save() # Generate node renumbered event Event.create_event(self.__node, EventCode.NodeRenumbered, '', EventSource.NodeDatabase, data = 'Old address: %s' % old_router_id)