CORD-1083 move CordSubscriberRoot to rcord repo

Change-Id: If017242579752aa2d813c1d462d36944fb735056
diff --git a/xos/admin.py b/xos/admin.py
new file mode 100644
index 0000000..84e0ecd
--- /dev/null
+++ b/xos/admin.py
@@ -0,0 +1,70 @@
+from django.contrib import admin
+
+#from services.volt.models import *
+from services.rcord.models import *
+from django import forms
+from django.utils.safestring import mark_safe
+from django.contrib.auth.admin import UserAdmin
+from django.contrib.admin.widgets import FilteredSelectMultiple
+from django.contrib.auth.forms import ReadOnlyPasswordHashField
+from django.contrib.auth.signals import user_logged_in
+from django.utils import timezone
+from django.contrib.contenttypes import generic
+from suit.widgets import LinkedSelect
+from core.admin import ServiceAppAdmin,SliceInline,ServiceAttrAsTabInline, ReadOnlyAwareAdmin, XOSTabularInline, ServicePrivilegeInline, TenantRootTenantInline, TenantRootPrivilegeInline
+from core.middleware import get_request
+
+from functools import update_wrapper
+from django.contrib.admin.views.main import ChangeList
+from django.core.urlresolvers import reverse
+from django.contrib.admin.utils import quote
+
+#class VOLTTenantInline(XOSTabularInline):
+#    model = VOLTTenant
+#    fields = ['provider_service', 'subscriber_root', 'service_specific_id']
+#    readonly_fields = ['provider_service', 'subscriber_root', 'service_specific_id']
+#    extra = 0
+#    max_num = 0
+#    suit_classes = 'suit-tab suit-tab-volttenants'
+#    fk_name = 'subscriber_root'
+#    verbose_name = 'subscribed tenant'
+#    verbose_name_plural = 'subscribed tenants'
+#
+#    @property
+#    def selflink_reverse_path(self):
+#        return "admin:cord_volttenant_change"
+
+class CordSubscriberRootForm(forms.ModelForm):
+    def __init__(self,*args,**kwargs):
+        super (CordSubscriberRootForm,self ).__init__(*args,**kwargs)
+        self.fields['kind'].widget.attrs['readonly'] = True
+        if (not self.instance) or (not self.instance.pk):
+            # default fields for an 'add' form
+            self.fields['kind'].initial = CORD_SUBSCRIBER_KIND
+
+    def save(self, commit=True):
+        return super(CordSubscriberRootForm, self).save(commit=commit)
+
+    class Meta:
+        model = CordSubscriberRoot
+        fields = '__all__'
+
+class CordSubscriberRootAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'id',  'name', )
+    list_display_links = ('backend_status_icon', 'id', 'name', )
+    fieldsets = [ (None, {'fields': ['backend_status_text', 'kind', 'name', 'service_specific_id', # 'service_specific_attribute',
+                                     'url_filter_level', "uplink_speed", "downlink_speed", "status", "enable_uverse", "cdn_enable"],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text', 'service_specific_attribute',)
+    form = CordSubscriberRootForm
+    inlines = (TenantRootPrivilegeInline) # VOLTTenantInline
+
+    suit_form_tabs =(('general', 'Cord Subscriber Root Details'),
+#        ('volttenants','VOLT Tenancy'),
+        ('tenantrootprivileges','Privileges')
+    )
+
+    def get_queryset(self, request):
+        return CordSubscriberRoot.get_tenant_objects_by_user(request.user)
+
+admin.site.register(CordSubscriberRoot, CordSubscriberRootAdmin)
diff --git a/xos/attic/cordsubscriberroot_bottom.py b/xos/attic/cordsubscriberroot_bottom.py
new file mode 100644
index 0000000..5821215
--- /dev/null
+++ b/xos/attic/cordsubscriberroot_bottom.py
@@ -0,0 +1 @@
+CordSubscriberRoot.setup_simple_attributes()
diff --git a/xos/attic/cordsubscriberroot_model.py b/xos/attic/cordsubscriberroot_model.py
new file mode 100644
index 0000000..e4ee81f
--- /dev/null
+++ b/xos/attic/cordsubscriberroot_model.py
@@ -0,0 +1,112 @@
+# 'simple_attributes' will be expanded into properties and setters that
+# store the attribute using self.set_attribute / self.get_attribute.
+
+simple_attributes = ( ("devices", []), )
+
+sync_attributes = ("firewall_enable",
+                   "firewall_rules",
+                   "url_filter_enable",
+                   "url_filter_rules",
+                   "cdn_enable",
+                   "uplink_speed",
+                   "downlink_speed",
+                   "enable_uverse",
+                   "status")
+
+def __init__(self, *args, **kwargs):
+    super(CordSubscriberRoot, self).__init__(*args, **kwargs)
+
+def find_device(self, mac):
+    for device in self.devices:
+        if device["mac"] == mac:
+            return device
+    return None
+
+def update_device(self, mac, **kwargs):
+    # kwargs may be "level" or "mac"
+    #    Setting one of these to None will cause None to be stored in the db
+    devices = self.devices
+    for device in devices:
+        if device["mac"] == mac:
+            for arg in kwargs.keys():
+                device[arg] = kwargs[arg]
+            self.devices = devices
+            return device
+    raise ValueError("Device with mac %s not found" % mac)
+
+def create_device(self, **kwargs):
+    if "mac" not in kwargs:
+        raise XOSMissingField("The mac field is required")
+
+    if self.find_device(kwargs['mac']):
+            raise XOSDuplicateKey("Device with mac %s already exists" % kwargs["mac"])
+
+    device = kwargs.copy()
+
+    devices = self.devices
+    devices.append(device)
+    self.devices = devices
+
+    return device
+
+def delete_device(self, mac):
+    devices = self.devices
+    for device in devices:
+        if device["mac"]==mac:
+            devices.remove(device)
+            self.devices = devices
+            return
+
+    raise ValueError("Device with mac %s not found" % mac)
+
+#--------------------------------------------------------------------------
+# Deprecated -- devices used to be called users
+
+def find_user(self, uid):
+    return self.find_device(uid)
+
+def update_user(self, uid, **kwargs):
+    return self.update_device(uid, **kwargs)
+
+def create_user(self, **kwargs):
+    return self.create_device(**kwargs)
+
+def delete_user(self, uid):
+    return self.delete_user(uid)
+
+# ------------------------------------------------------------------------
+
+@property
+def services(self):
+    return {"cdn": self.cdn_enable,
+            "url_filter": self.url_filter_enable,
+            "firewall": self.firewall_enable}
+
+@services.setter
+def services(self, value):
+    pass
+
+def invalidate_related_objects(self):
+    # Dirty all vSGs related to this subscriber, so the vSG synchronizer

+    # will run.

+

+    # TODO: This should be reimplemented to use a watcher instead.

+

+    # NOTE: "vOLT" and "vCPE" are hardcoded below. They had better agree

+    # with the kinds defined in the vOLT and vCPE models.

+

+    for tenant in self.subscribed_tenants.all():

+        if tenant.kind == "vOLT":

+            for inner_tenant in tenant.subscribed_tenants.all():

+                if inner_tenant.kind == "vCPE":

+                    inner_tenant.save()

+

+def save(self, *args, **kwargs):

+    self.validate_unique_service_specific_id(none_okay=True)

+    if (not hasattr(self, 'caller') or not self.caller.is_admin):

+        if (self.has_field_changed("service_specific_id")):

+            raise XOSPermissionDenied("You do not have permission to change service_specific_id")

+    super(CordSubscriberRoot, self).save(*args, **kwargs)

+

+    self.invalidate_related_objects()
+
diff --git a/xos/attic/header.py b/xos/attic/header.py
new file mode 100644
index 0000000..afa4e4c
--- /dev/null
+++ b/xos/attic/header.py
@@ -0,0 +1,21 @@
+from django.db import models
+from django.db.models import *
+from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, TenantRoot, NetworkParameter, NetworkParameterType, Port, AddressPool, User
+from core.models.plcorebase import StrippedCharField
+import os
+from django.db import models, transaction
+from django.forms.models import model_to_dict
+from django.db.models import Q
+from operator import itemgetter, attrgetter, methodcaller
+from core.models import Tag
+from core.models.service import LeastLoadedNodeScheduler
+from services.vrouter.models import VRouterService, VRouterTenant
+import traceback
+from xos.exceptions import *
+from xos.config import Config
+
+class ConfigurationError(Exception):
+    pass
+
+CORD_SUBSCRIBER_KIND = "CordSubscriberRoot"
+
diff --git a/xos/header.py b/xos/header.py
new file mode 100644
index 0000000..afa4e4c
--- /dev/null
+++ b/xos/header.py
@@ -0,0 +1,21 @@
+from django.db import models
+from django.db.models import *
+from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, TenantRoot, NetworkParameter, NetworkParameterType, Port, AddressPool, User
+from core.models.plcorebase import StrippedCharField
+import os
+from django.db import models, transaction
+from django.forms.models import model_to_dict
+from django.db.models import Q
+from operator import itemgetter, attrgetter, methodcaller
+from core.models import Tag
+from core.models.service import LeastLoadedNodeScheduler
+from services.vrouter.models import VRouterService, VRouterTenant
+import traceback
+from xos.exceptions import *
+from xos.config import Config
+
+class ConfigurationError(Exception):
+    pass
+
+CORD_SUBSCRIBER_KIND = "CordSubscriberRoot"
+
diff --git a/xos/rcord-onboard.yaml b/xos/rcord-onboard.yaml
new file mode 100644
index 0000000..8e7dac5
--- /dev/null
+++ b/xos/rcord-onboard.yaml
@@ -0,0 +1,17 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard rcord models
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    library#rcord:
+      type: tosca.nodes.ServiceController
+      properties:
+          base_url: file:///opt/cord/orchestration/profiles/rcord/xos/
+          # The following will concatenate with base_url automatically, if
+          # base_url is non-null.
+          xproto: ./
+          admin: admin.py
diff --git a/xos/rcord.xproto b/xos/rcord.xproto
new file mode 100644
index 0000000..f2e6ac8
--- /dev/null
+++ b/xos/rcord.xproto
@@ -0,0 +1,18 @@
+option name = "rcord";
+option verbose_name = "RCORD Profile";
+
+message CordSubscriberRoot (TenantRoot){
+     option kind = "CordSubscriberRoot";
+
+     required bool firewall_enable = 1 [default = False, null = False, db_index = False, blank = True];
+     optional string firewall_rules = 2 [default = "accept all anywhere anywhere", null = True, db_index = False, blank = True];
+     required bool url_filter_enable = 3 [default = False, null = False, db_index = False, blank = True];
+     optional string url_filter_rules = 4 [default = "allow all", null = True, db_index = False, blank = True];
+     required string url_filter_level = 5 [default = "PG", max_length = 30, content_type = "stripped", blank = False, null = False, db_index = False];
+     required bool cdn_enable = 6 [default = False, null = False, db_index = False, blank = True];
+     required bool is_demo_user = 7 [default = False, null = False, db_index = False, blank = True];
+     required int32 uplink_speed = 8 [default = 1000000000, null = False, db_index = False, blank = False];
+     required int32 downlink_speed = 9 [default = 1000000000, null = False, db_index = False, blank = False];
+     required bool enable_uverse = 10 [default = True, null = False, db_index = False, blank = True];
+     required string status = 11 [default = "enabled", choices = "(('enabled', 'Enabled'), ('suspended', 'Suspended'), ('delinquent', 'Delinquent'), ('copyrightviolation', 'Copyright Violation'))", max_length = 30, content_type = "stripped", blank = False, null = False, db_index = False];
+}