Exemple #1
0
 def handle_add(self, *args, **options):
     if "username" not in options:
         raise CommandError("Username is not set")
     if "email" not in options:
         raise CommandError("Email is not set")
     if "pwgen" in options:
         passwd = "".join(
             random.choice(self.pwset) for _ in range(self.PWLEN))
     else:
         passwd = None
     if not passwd:
         raise CommandError("Password is not set")
     permissions = set()
     if not options.get("template"):
         raise CommandError("template permission not set")
     for t in options["template"]:
         if t not in self.TEMPLATES:
             raise CommandError("Invalid template '%s'" % t)
         permissions.update(self.TEMPLATES[t])
     if not permissions:
         raise CommandError("No permissions set")
     # Create user
     u = User(username=options["username"],
              email=options["email"],
              is_active=True)
     u.set_password(passwd)
     u.save()
     for p in permissions:
         try:
             perm = Permission.objects.get(name=p)
         except Permission.DoesNotExist:
             perm = Permission(name=p)
             perm.save()
         perm.users.add(u)
     print(passwd)
Exemple #2
0
 def update_m2m(self, o, name, values):
     if values is None:
         return  # Do not touch
     if name == "permissions":
         Permission.set_group_permissions(group=o, perms=values)
     else:
         super().update_m2m(o, name, values)
Exemple #3
0
 def update_m2m(self, o, name, values):
     if values is None:
         return  # Do not touch
     if name == "permissions":
         Permission.set_user_permissions(user=o, perms=values)
     else:
         super(UserApplication, self).update_m2m(o, name, values)
Exemple #4
0
    def handle(self, *args, **options):
        from noc.lib.app.site import site

        site.service = get_service()
        try:
            Permission.sync()
        except ValueError as e:
            self.die(str(e))
Exemple #5
0
    def handle(self, *args, **options):
        from noc.lib.app.site import site

        connect()
        # Install service stub
        site.service = get_service()
        # Synchronize permissions
        try:
            Permission.sync()
        except ValueError as e:
            self.die(str(e))
Exemple #6
0
 def view_view(self, request, refbook_id):
     """
     Refbook preview
     :param request:
     :param refbook_id:
     :return:
     """
     rb = get_object_or_404(RefBook, id=int(refbook_id))
     can_edit = not rb.is_builtin and Permission.has_perm(
         request.user, "main.change_refbookdata"
     )
     queryset = rb.refbookdata_set.all()
     # Search
     if request.GET and "query" in request.GET and request.GET["query"]:
         query = request.GET["query"]
         # Build query clause
         w = []
         p = []
         for f in rb.refbookfield_set.filter(search_method__isnull=False):
             x = f.get_extra(query)
             if not x:
                 continue
             w += x["where"]
             p += x["params"]
         w = " OR ".join(["(%s)" % xx for xx in w])
         queryset = queryset.extra(where=["(%s)" % w], params=p)
     else:
         query = ""
     # Use generic view for final result
     request._gv_queryset = queryset
     request._gv_ctx = {"rb": rb, "can_edit": can_edit, "query": query, "app": self}
     return RefBookList().get(request)
Exemple #7
0
 def view_new(self, request, refbook_id):
     """
     Create refbook record
     :param request:
     :param refbook_id:
     :return:
     """
     rb = get_object_or_404(RefBook, id=int(refbook_id))
     can_edit = not rb.is_builtin and Permission.has_perm(
         request.user, "main.change_refbookdata"
     )
     if not can_edit:
         return self.response_forbidden("Read-only refbook")
     if request.POST:  # Edit refbook
         if not can_edit:
             return self.response_forbidden("Read-only refbook")
         # Retrieve record data
         fns = [int(k[6:]) for k in request.POST if k.startswith("field_")]
         data = ["" for i in range(max(fns) + 1)]
         for i in fns:
             data[i] = request.POST["field_%d" % i]
         rbr = RefBookData(ref_book=rb, value=data)
         rbr.save()
         self.message_user(request, "Record added")
         return self.response_redirect("main:refbook:item", rb.id, rbr.id)
     return self.render(request, "new.html", {"rb": rb})
Exemple #8
0
 def has_secret(self):
     """
     Check current user has *secret* permission on given app
     :return:
     """
     perm_name = "%s:secret" % (self.get_app_id().replace(".", ":"))
     return perm_name in Permission.get_effective_permissions(get_user())
Exemple #9
0
 def view_edit(self, request, refbook_id, record_id=0):
     """
     Edit item
     :param request:
     :param refbook_id:
     :param record_id:
     :return:
     """
     rb = get_object_or_404(RefBook, id=int(refbook_id))
     rbr = get_object_or_404(RefBookData, id=int(record_id), ref_book=rb)
     can_edit = not rb.is_builtin and Permission.has_perm(
         request.user, "main.change_refbookdata")
     if not can_edit:
         return self.response_forbidden("Read-only refbook")
     if request.POST:  # Edit refbook
         if not can_edit:
             return self.response_forbidden("Read-only refbook")
         # Retrieve record data
         fns = [
             int(k[6:]) for k in six.iterkeys(request.POST)
             if k.startswith("field_")
         ]
         data = ["" for i in range(max(fns) + 1)]
         for i in fns:
             data[i] = request.POST["field_%d" % i]
         rbr.value = data
         rbr.save()
         self.message_user(request, "Record updated successfully")
         return self.response_redirect("main:refbook:item", rb.id, rbr.id)
     return self.render(request, "edit.html", {"rb": rb, "record": rbr})
Exemple #10
0
 def save(self, *args, **kwargs):
     super().save(*args, **kwargs)
     # Create permission if required
     if self.permission_name:
         try:
             Permission.objects.get(name=self.effective_permission_name)
         except Permission.DoesNotExist:
             Permission(name=self.effective_permission_name).save()
Exemple #11
0
 def view_desktop(self, request):
     """
     Render application root template
     """
     cp = CPClient()
     ext_apps = [
         a for a in self.site.apps
         if isinstance(self.site.apps[a], ExtApplication)
     ]
     apps = [a.split(".") for a in sorted(ext_apps)]
     # Prepare settings
     favicon_url = config.customization.favicon_url
     if favicon_url.endswith(".png"):
         favicon_mime = "image/png"
     elif favicon_url.endswith(".jpg") or favicon_url.endswith(".jpeg"):
         favicon_mime = "image/jpeg"
     else:
         favicon_mime = None
     if request.user.is_authenticated():
         enable_search = Permission.has_perm(request.user,
                                             "main:search:launch")
     else:
         enable_search = False
     setup = {
         "system_uuid": cp.system_uuid,
         "installation_name": config.installation_name,
         "theme": config.web.theme,
         "logo_url": config.customization.logo_url,
         "logo_width": config.customization.logo_width,
         "logo_height": config.customization.logo_height,
         "brand": version.brand,
         "branding_color": config.customization.branding_color,
         "branding_background_color":
         config.customization.branding_background_color,
         "favicon_url": favicon_url,
         "favicon_mime": favicon_mime,
         "debug_js": False,
         "gitlab_url": config.gitlab_url,
         "collections_allow_sharing": config.collections.allow_sharing,
         "collections_project_id": config.collections.project_id,
         "enable_gis_base_osm": config.gis.enable_osm,
         "enable_gis_base_google_sat": config.gis.enable_google_sat,
         "enable_gis_base_google_roadmap": config.gis.enable_google_roadmap,
         "trace_extjs_events": False,
         "preview_theme": config.customization.preview_theme,
         "enable_search": enable_search,
         "help_base_url": config.help.base_url,
         "help_branch": config.help.branch,
         "help_language": config.help.language,
         "enable_remote_system_last_extract_info":
         config.web.enable_remote_system_last_extract_info,
         "timezone": config.timezone,
     }
     return self.render(request,
                        "desktop.html",
                        language=self.get_language(request),
                        apps=apps,
                        setup=setup)
Exemple #12
0
 def instance_to_dict_get(self, o, fields=None):
     r = super().instance_to_dict(o, fields)
     r["permissions"] = self.apps_permissions_list()
     current_perms = Permission.get_group_permissions(o)
     if current_perms:
         for p in r["permissions"]:
             if p["name"] in current_perms:
                 p["status"] = True
     return r
Exemple #13
0
 def instance_to_dict_get(self, o, fields=None):
     r = super(UserApplication, self).instance_to_dict(o, fields)
     del r["password"]
     r["permissions"] = self.apps_permissions_list()
     current_perms = Permission.get_user_permissions(o)
     if current_perms:
         for p in r["permissions"]:
             if p["name"] in current_perms:
                 p["status"] = True
     return r
Exemple #14
0
 def api_settings(self, request):
     cp = CPClient()
     # Prepare settings
     favicon_url = config.customization.favicon_url
     if favicon_url.endswith(".png"):
         favicon_mime = "image/png"
     elif favicon_url.endswith(".jpg") or favicon_url.endswith(".jpeg"):
         favicon_mime = "image/jpeg"
     else:
         favicon_mime = None
     if request.user.is_authenticated():
         enable_search = Permission.has_perm(request.user,
                                             "main:search:launch")
     else:
         enable_search = False
     language = self.get_language(request)
     return {
         "system_uuid": cp.system_uuid or None,
         "brand": version.brand,
         "installation_name": config.installation_name,
         "preview_theme": config.customization.preview_theme,
         "language": language,
         "logo_url": config.customization.logo_url,
         "logo_width": config.customization.logo_width,
         "logo_height": config.customization.logo_height,
         "branding_color": config.customization.branding_color,
         "branding_background_color":
         config.customization.branding_background_color,
         "favicon_mime": favicon_mime,
         "favicon_url": favicon_url,
         "enable_search": enable_search,
         "gitlab_url": config.gitlab_url,
         "collections": {
             "allow_sharing": config.collections.allow_sharing,
             "project_id": config.collections.project_id,
         },
         "gis": {
             "base": {
                 "enable_osm": config.gis.enable_osm,
                 "enable_google_sat": config.gis.enable_google_sat,
                 "enable_google_roadmap": config.gis.enable_google_roadmap,
             }
         },
         "traceExtJSEvents": False,
         "helpUrl": config.help.base_url,
         "helpBranch": config.help.branch,
         "helpLanguage": config.help.language,
         "timezone": config.timezone,
         "enable_remote_system_last_extract_info":
         config.web.enable_remote_system_last_extract_info,
         "theme": config.web.theme,
     }
Exemple #15
0
 def view_item(self, request, refbook_id, record_id):
     """
     Item preview
     :param request:
     :param refbook_id:
     :param record_id:
     :return:
     """
     rb = get_object_or_404(RefBook, id=int(refbook_id))
     rbr = get_object_or_404(RefBookData, id=int(record_id), ref_book=rb)
     can_edit = not rb.is_builtin and Permission.has_perm(
         request.user, "main.change_refbookdata"
     )
     return self.render(request, "item.html", {"rb": rb, "record": rbr, "can_edit": can_edit})
Exemple #16
0
 def view_delete(self, request, refbook_id, record_id):
     """
     Delete refbook record
     :param request:
     :param refbook_id:
     :param record_id:
     :return:
     """
     rb = get_object_or_404(RefBook, id=int(refbook_id))
     can_edit = not rb.is_builtin and Permission.has_perm(
         request.user, "main.change_refbookdata")
     if not can_edit:
         return self.response_forbidden()
     rbd = get_object_or_404(RefBookData, ref_book=rb, id=int(record_id))
     rbd.delete()
     self.message_user(request, "Record deleted")
     return self.response_redirect("main:refbook:view", rb.id)
Exemple #17
0
    def get_launch_info(self, request):
        """
        Return desktop launch information
        """
        from noc.aaa.models.permission import Permission

        user = request.user
        # Amount of characters to strip
        lps = len(self.get_app_id()) + 1
        # Get effective user permissions
        user_perms = Permission.get_effective_permissions(user)
        # Leave only application permissions
        # and strip <module>:<app>:
        app_perms = [p[lps:] for p in user_perms & self.get_permissions()]
        return {
            "class": self.js_app_class,
            "title": unicode(self.title),
            "params": {
                "url": self.menu_url,
                "permissions": app_perms,
                "app_id": self.app_id,
                "link": self.link,
            },
        }
Exemple #18
0
 def prefix_contents(self, request, prefix):
     vrf = prefix.vrf
     # List of nested prefixes
     # @todo: prefetch_related
     prefixes = list(
         prefix.children_set.select_related().order_by("prefix"))
     # Bulk utilization
     Prefix.update_prefixes_usage(prefixes)
     # Free prefixes
     free_prefixes = list(
         IP.prefix(prefix.prefix).iter_free([pp.prefix for pp in prefixes]))
     # Get permissions
     user = request.user
     can_view = prefix.can_view(user)
     can_change = prefix.can_change(user)
     can_bind_vc = can_change and Permission.has_perm(
         user, "ip:ipam:bind_vc")
     can_change_maintainers = user.is_superuser
     can_add_prefix = can_change
     can_add_address = can_change and len(prefixes) == 0
     # Bookmarks
     has_bookmark = prefix.has_bookmark(user)
     bookmarks = set(b.prefix for b in PrefixBookmark.user_bookmarks(
         user, vrf=vrf, afi=prefix.afi))
     l_prefixes = sorted(
         ([(IP.prefix(pp.prefix), pp, pp.prefix in bookmarks)
           for pp in prefixes] + [(pp, None, False)
                                  for pp in free_prefixes]),
         key=lambda x: x[0],
     )
     # List of nested addresses
     addresses = list(
         prefix.address_set.select_related().order_by("address"))
     # Ranges
     ranges = []
     rs = []
     max_slots = 0
     r_spots = []
     allocated_addresses = set()
     if addresses:
         # Assign ranges colors
         ranges = list(prefix.address_ranges)
         for r, c in zip(ranges, get_colors(len(ranges))):
             r.color = c
             # Schedule ranges
         r_changes = {
         }  # Address -> (set of entering ranges, set of leaving ranges)
         for r in ranges:
             if r.from_address not in r_changes:
                 r_changes[r.from_address] = (set(), set())
             if r.to_address not in r_changes:
                 r_changes[r.to_address] = (set(), set())
             r_changes[r.from_address][0].add(r)
             r_changes[r.to_address][1].add(r)
             # <!>
             n = (IP.prefix(r.to_address) + 1).address
             if n not in r_changes:
                 r_changes[n] = (set(), set())
         r_spots = list(r_changes)
         # Allocate slots
         used_slots = set()
         free_slots = set()
         r_slots = {}  # Range -> slot
         max_slots = 0
         rs = sorted([[IP.prefix(i), d, []] for i, d in r_changes.items()],
                     key=itemgetter(0))
         for address, d, x in rs:
             entering, leaving = d
             for r in entering:
                 if not free_slots:
                     free_slots.add(max_slots)
                     max_slots += 1
                 spt = free_slots.pop()
                 used_slots.add(spt)
                 r_slots[r] = spt
             for r in leaving:
                 spt = r_slots[r]
                 used_slots.remove(spt)
                 free_slots.add(spt)
         # Assign ranges to slots
         slots = [None] * max_slots
         for r in rs:
             address, [entering, leaving], _ = r
             for e in entering:
                 slots[r_slots[e]] = e
             r[2] = slots[:]
             for ll in leaving:
                 slots[r_slots[ll]] = None
         # Assign slots to addresses
         c = [None] * max_slots
         rrs = rs[:]
         cr = rrs.pop(0) if rrs else None
         for a in addresses:
             allocated_addresses.add(str(a.address))
             address = IP.prefix(a.address)
             while cr and address >= cr[0]:
                 c = cr[2]
                 if rrs:
                     cr = rrs.pop(0)
                 else:
                     break
             a.slots = c
     # Address spot
     if can_add_address:
         c = [None] * max_slots
         rrs = rs[:]
         if rrs:
             cr = rrs.pop(0)
         else:
             cr = None
         spot = []
         for a in self.get_prefix_spot(prefix, extra=r_spots):
             if cr and a is not None and a == cr[0]:
                 c = [None if cc is None else cc.id for cc in cr[2]]
                 if rrs:
                     cr = rrs.pop(0)
             spot += [(None if a is None else a.address, c)]
         # spot += [(None if a is None else a.address, c, a in special_addr)]
         # spot = ujson.dumps(spot)
         # spot = JSONEncoder(ensure_ascii=False).encode(spot)
     else:
         spot = None
     can_ping = spot is not None and len(
         [a for a in addresses if a.managed_object]) > 0
     prefix_info = self.get_info_block(prefix.afi, prefix, addresses)
     path = [Prefix.objects.get(id=pp) for pp in prefix.get_path()]
     return {
         "id":
         prefix.id,
         "name":
         prefix.prefix,
         "vrf":
         prefix.vrf.id,
         "vrf__label":
         "%s (%s)" % (prefix.vrf.name, prefix.vrf.vpn_id),
         "description":
         prefix.description,
         "afi":
         prefix.afi,
         "profile":
         prefix.profile.name,
         "state":
         prefix.state.name,
         "maintainers": [m.username for m in prefix.maintainers],
         "has_bookmark":
         has_bookmark,
         "permissions": {
             "view": can_view,
             "change": can_change,
             "bind_vc": can_bind_vc,
             "change_maintainers": can_change_maintainers,
             "add_prefix": can_add_prefix,
             "delete_prefix": True,
             "add_address": can_add_address,
             "ping": can_ping,
         },
         "path": [{
             "id": p.id,
             "parent_id": p.parent_id,
             "name": p.prefix
         } for p in path],
         "prefixes": [{
             "id": p.id,
             "name": p.prefix,
             "has_bookmark": is_bookmarks,
             "description": p.description,
             "afi": p.afi,
             "project": p.project.code if p.project else None,
             "as": "AS%d" % p.asn.asn if p.asn else None,
             "vc": p.vc.name if p.vc else None,
             "tt": p.tt,
             "usage": p.usage_percent,
             "address_usage": p.address_usage_percent,
             "labels": p.labels,
             "state": p.state.name,
             "state_desc": p.state.description,
             "isFree": False,
         } if p else {
             "name": ip.prefix,
             "isFree": True
         } for ip, p, is_bookmarks in l_prefixes],
         "addresses":
         sorted(
             [{
                 "id":
                 a.id,
                 "name":
                 a.name,
                 "address":
                 a.address,
                 "state":
                 a.state.name,
                 "fqdn":
                 a.fqdn if a.fqdn else None,
                 "mac":
                 a.mac if a.mac else None,
                 "mo_id":
                 a.managed_object.id if a.managed_object else None,
                 "mo_name":
                 a.managed_object.name if a.managed_object else None,
                 "is_router":
                 a.managed_object.is_router if a.managed_object else None,
                 "project":
                 a.project.code if a.project else None,
                 "subinterface":
                 a.subinterface if a.subinterface else None,
                 "short_desc":
                 a.short_description,
                 "desc":
                 a.description,
                 "source": {
                     "M": "Manual",
                     "i": "Interface",
                     "m": "Mgmt",
                     "d": "DHCP",
                     "n": "Neighbor",
                 }.get(a.source, "-"),
                 "tt":
                 a.tt,
                 "labels":
                 a.labels,
                 "isFree":
                 False,
             } for a in addresses] + ([{
                 "address": z[0],
                 "isFree": True
             } for z in spot if str(z[0]) not in allocated_addresses]
                                      if spot else []),
             key=lambda x: IP.prefix(x["address"]),
         ),
         "info":
         dict(prefix_info),
         "ranges": [{
             "name": r.name,
             "description": r.description,
             "from_address": r.from_address,
             "to_address": r.to_address,
             "color": r.color,
         } for r in ranges],
         "bookmarks": [{
             "id": b.id,
             "text": b.prefix
         } for b in PrefixBookmark.user_bookmarks(
             user, vrf=vrf, afi=prefix.afi)],
     }
Exemple #19
0
def test_permissions():
    site.service = get_service()
    Permission.sync()
    assert Permission.objects.count() > 0
Exemple #20
0
 def check(self, app, user, obj=None):
     return DBPermission.has_perm(user, self.get_permission(app))
Exemple #21
0
 def view_vrf_index(self, request, vrf_id, afi, prefix):
     """
     Display VRF Index
     """
     # Validate
     vrf = self.get_object_or_404(VRF, id=int(vrf_id))
     if (afi == "4" and (not is_ipv4_prefix(prefix)) or not vrf.afi_ipv4) or (
         afi == "6" and (not is_ipv6_prefix(prefix) or not vrf.afi_ipv6)
     ):
         return self.response_forbidden("Invalid prefix")
     prefix = self.get_object_or_404(Prefix, vrf=vrf, afi=afi, prefix=prefix)
     # Get prefix path
     path = []
     p = prefix.parent
     while p:
         path = [p] + path
         p = p.parent
     # List of nested prefixes
     # @todo: prefetch_related
     prefixes = list(prefix.children_set.select_related().order_by("prefix"))
     # Bulk utilization
     Prefix.update_prefixes_usage(prefixes)
     # Get permissions
     user = request.user
     can_view = prefix.can_view(user)
     can_change = prefix.can_change(user)
     can_bind_vc = can_change and Permission.has_perm(user, "ip:ipam:bind_vc")
     can_change_maintainers = user.is_superuser
     can_add_prefix = can_change
     can_add_address = can_change and len(prefixes) == 0
     can_edit_special = prefix.effective_prefix_special_address == "I"
     # Bookmarks
     has_bookmark = prefix.has_bookmark(user)
     bookmarks = PrefixBookmark.user_bookmarks(user, vrf=vrf, afi=afi)
     s_bookmarks = set(b.prefix for b in bookmarks)
     # Add free prefixes
     free_prefixes = list(IP.prefix(prefix.prefix).iter_free([pp.prefix for pp in prefixes]))
     l_prefixes = sorted(
         (
             [(True, IP.prefix(pp.prefix), pp, pp.prefix in s_bookmarks) for pp in prefixes]
             + [(False, pp, None, None) for pp in free_prefixes]
         ),
         key=lambda x: x[1],
     )
     # List of nested addresses
     # @todo: prefetch_related
     addresses = list(prefix.address_set.select_related().order_by("address"))
     # Prepare block info
     prefix_info = [("Network", prefix.prefix)]
     if afi == "4":
         prefix_info += [
             ("Broadcast", prefix.broadcast),
             ("Netmask", prefix.netmask),
             ("Widlcard", prefix.wildcard),
             ("Size", prefix.size),
             ("Usage", prefix.usage_percent),
             ("Usage Address", prefix.address_usage_percent),
         ]
     if addresses:
         prefix_info += [("Used addresses", len(addresses))]
         if afi == "4":
             free = prefix.size - len(addresses)
             prefix_info += [("Free addresses", free - 2 if free >= 2 else free)]
     # Prefix discovery
     dmap = {"E": "Enabled", "D": "Disabled"}
     if prefix.prefix_discovery_policy == "P":
         t = "Profile (%s)" % dmap[prefix.profile.prefix_discovery_policy]
     else:
         t = dmap[prefix.prefix_discovery_policy]
     prefix_info += [("Prefix Discovery", t)]
     # Address discovery
     if prefix.address_discovery_policy == "P":
         t = "Profile (%s)" % dmap[prefix.profile.address_discovery_policy]
     else:
         t = dmap[prefix.address_discovery_policy]
     prefix_info += [("Address Discovery", t)]
     # Source
     prefix_info += [
         (
             "Source",
             {"M": "Manual", "i": "Interface", "w": "Whois Route", "n": "Neighbor"}.get(
                 prefix.source, "-"
             ),
         )
     ]
     #
     # Add custom fields
     for f in CustomField.table_fields("ip_prefix"):
         v = getattr(prefix, f.name)
         prefix_info += [(f.label, v if v is not None else "")]
     # Ranges
     ranges = []
     rs = []
     max_slots = 0
     r_spots = []
     if addresses:
         # Assign ranges colors
         ranges = list(prefix.address_ranges)
         for r, c in zip(ranges, get_colors(len(ranges))):
             r.color = c
             # Schedule ranges
         r_changes = {}  # Address -> (set of entering ranges, set of leaving ranges)
         for r in ranges:
             if r.from_address not in r_changes:
                 r_changes[r.from_address] = (set(), set())
             if r.to_address not in r_changes:
                 r_changes[r.to_address] = (set(), set())
             r_changes[r.from_address][0].add(r)
             r_changes[r.to_address][1].add(r)
             # <!>
             n = (IP.prefix(r.to_address) + 1).address
             if n not in r_changes:
                 r_changes[n] = (set(), set())
         r_spots = list(six.iterkeys(r_changes))
         # Allocate slots
         used_slots = set()
         free_slots = set()
         r_slots = {}  # Range -> slot
         max_slots = 0
         rs = sorted(
             ([IP.prefix(i), d, []] for i, d in six.iteritems(r_changes)), key=itemgetter(0)
         )
         for address, d, x in rs:
             entering, leaving = d
             for r in entering:
                 if not free_slots:
                     free_slots.add(max_slots)
                     max_slots += 1
                 s = free_slots.pop()
                 used_slots.add(s)
                 r_slots[r] = s
             for r in leaving:
                 s = r_slots[r]
                 used_slots.remove(s)
                 free_slots.add(s)
         # Assign ranges to slots
         slots = [None] * max_slots
         for r in rs:
             address, [entering, leaving], _ = r
             for e in entering:
                 slots[r_slots[e]] = e
             r[2] = slots[:]
             for l in leaving:
                 slots[r_slots[l]] = None
         # Assign slots to addresses
         c = [None] * max_slots
         rrs = rs[:]
         cr = rrs.pop(0) if rrs else None
         for a in addresses:
             address = IP.prefix(a.address)
             while cr and address >= cr[0]:
                 c = cr[2]
                 if rrs:
                     cr = rrs.pop(0)
                 else:
                     break
             a.slots = c
     # Address spot
     if can_add_address:
         special_addr = IP.prefix(prefix.prefix).special_addresses
         c = [None] * max_slots
         rrs = rs[:]
         if rrs:
             cr = rrs.pop(0)
         else:
             cr = None
         spot = []
         for a in self.get_prefix_spot(prefix, extra=r_spots):
             if cr and a is not None and a == cr[0]:
                 c = [None if cc is None else cc.id for cc in cr[2]]
                 if rrs:
                     cr = rrs.pop(0)
             spot += [(None if a is None else a.address, c, a in special_addr)]
         spot = ujson.dumps(spot)
     else:
         spot = None
     can_ping = spot is not None and len([a for a in addresses if a.managed_object]) > 0
     # Build custom styles
     styles = {}
     if prefix.profile.style:
         styles[prefix.profile.style.css_class_name] = prefix.profile.style.css
     for p in prefixes:
         if p.profile.style and p.profile.style.css_class_name not in styles:
             styles[p.profile.style.css_class_name] = p.profile.style.css
     for a in addresses:
         if a.profile.style and a.profile.style.css_class_name not in styles:
             styles[a.profile.style.css_class_name] = a.profile.style.css
     styles = "\n".join(six.itervalues(styles))
     # Render
     return self.render(
         request,
         "vrf_index.html.j2",
         user=request.user,
         vrf=vrf,
         prefix=prefix,
         path=path,
         prefixes=prefixes,
         addresses=addresses,
         prefix_info=prefix_info,
         display_empty_message=not addresses and not prefixes,
         can_view=can_view,
         can_change=can_change,
         can_bind_vc=can_bind_vc,
         can_change_maintainers=can_change_maintainers,
         can_add_prefix=can_add_prefix,
         can_add_address=can_add_address,
         can_edit_special=can_edit_special,
         has_bookmark=has_bookmark,
         bookmarks=bookmarks,
         spot=spot,
         can_ping=can_ping,
         styles=styles,
         ranges=ranges,
         max_slots=max_slots,
         l_prefixes=l_prefixes,
     )