CORD-1250 Update to new Service/Tenancy models
Change-Id: I37e73892af3d33163d60cc0095d9bf8368ec3e22
diff --git a/xos/admin.py b/xos/admin.py
index d485b9a..f8bd1ca 100644
--- a/xos/admin.py
+++ b/xos/admin.py
@@ -10,7 +10,7 @@
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, TenantAttrAsTabInline
+from core.admin import ServiceAppAdmin,SliceInline,ServiceAttrAsTabInline, ReadOnlyAwareAdmin, XOSTabularInline, ServicePrivilegeInline, ServiceInstanceAttrAsTabInline, SubscriberLinkInline, ProviderLinkInline, ProviderDependencyInline,SubscriberDependencyInline
from core.middleware import get_request
from functools import update_wrapper
@@ -26,7 +26,7 @@
list_display_links = ('backend_status_icon', 'name', )
fieldsets = [(None, {'fields': ['backend_status_text', 'name','enabled','versionNumber', 'description',"view_url","icon_url", "rest_hostname", "rest_port", "no_container" ], 'classes':['suit-tab suit-tab-general']})]
readonly_fields = ('backend_status_text', )
- inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
+ inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline, ProviderDependencyInline,SubscriberDependencyInline]
extracontext_registered_admins = True
@@ -36,6 +36,7 @@
('administration', 'Administration'),
('slices','Slices'),
('serviceattrs','Additional Attributes'),
+ ('servicetenants', 'Dependencies'),
('serviceprivileges','Privileges'),
)
@@ -48,14 +49,14 @@
class ONOSAppForm(forms.ModelForm):
def __init__(self,*args,**kwargs):
super (ONOSAppForm,self ).__init__(*args,**kwargs)
- self.fields['kind'].widget.attrs['readonly'] = True
- self.fields['provider_service'].queryset = ONOSService.objects.all()
+# self.fields['kind'].widget.attrs['readonly'] = True
+ self.fields['owner'].queryset = ONOSService.objects.all()
if (not self.instance) or (not self.instance.pk):
# default fields for an 'add' form
- self.fields['kind'].initial = ONOS_KIND
- self.fields['creator'].initial = get_request().user
+# self.fields['kind'].initial = ONOS_KIND
+# self.fields['creator'].initial = get_request().user
if ONOSService.objects.exists():
- self.fields["provider_service"].initial = ONOSService.objects.all()[0]
+ self.fields["owner"].initial = ONOSService.objects.all()[0]
def save(self, commit=True):
return super(ONOSAppForm, self).save(commit=commit)
@@ -67,14 +68,13 @@
class ONOSAppAdmin(ReadOnlyAwareAdmin):
list_display = ('backend_status_icon', 'name', )
list_display_links = ('backend_status_icon', 'name')
- fieldsets = [ (None, {'fields': ['backend_status_text', 'kind', 'name', 'provider_service', 'subscriber_service', 'service_specific_attribute', "dependencies",
- 'creator'],
+ fieldsets = [ (None, {'fields': ['backend_status_text', 'name', 'owner', 'service_specific_attribute', "dependencies"],
'classes':['suit-tab suit-tab-general']})]
- readonly_fields = ('backend_status_text', 'instance', 'service_specific_attribute')
- inlines = [TenantAttrAsTabInline]
+ readonly_fields = ('backend_status_text', 'service_specific_attribute')
+ inlines = [ServiceInstanceAttrAsTabInline, ProviderLinkInline, SubscriberLinkInline]
form = ONOSAppForm
- suit_form_tabs = (('general','Details'), ('tenantattrs', 'Attributes'))
+ suit_form_tabs = (('general','Details'), ('serviceinstanceattrs', 'Attributes'), ('servicelinks','Links'),)
def get_queryset(self, request):
return ONOSApp.select_by_user(request.user)
diff --git a/xos/api/service/onos.py b/xos/api/service/onos.py
deleted file mode 100644
index 5861947..0000000
--- a/xos/api/service/onos.py
+++ /dev/null
@@ -1,87 +0,0 @@
-from rest_framework.decorators import api_view
-from rest_framework.response import Response
-from rest_framework.reverse import reverse
-from rest_framework import serializers
-from rest_framework import generics
-from rest_framework import status
-from core.models import *
-from django.forms import widgets
-from services.onos.models import ONOSService
-from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
-from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
-
-class ONOSServiceSerializer(PlusModelSerializer):
- id = ReadOnlyField()
- rest_hostname = serializers.CharField(required=False)
- rest_port = serializers.CharField(default="8181")
- no_container = serializers.BooleanField(default=False)
- node_key = serializers.CharField(required=False)
-
- humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
- class Meta:
- model = ONOSService
- fields = ('humanReadableName', 'id', 'rest_hostname', 'rest_port', 'no_container', 'node_key')
-
- def getHumanReadableName(self, obj):
- return obj.__unicode__()
-
-class ServiceAttributeSerializer(serializers.Serializer):
- id = ReadOnlyField()
- name = serializers.CharField(required=False)
- value = serializers.CharField(required=False)
-
-class ONOSServiceViewSet(XOSViewSet):
- base_name = "onos"
- method_name = "onos"
- method_kind = "viewset"
- queryset = ONOSService.objects.all()
- serializer_class = ONOSServiceSerializer
-
- custom_serializers = {"set_attribute": ServiceAttributeSerializer}
-
- @classmethod
- def get_urlpatterns(self, api_path="^"):
- patterns = super(ONOSServiceViewSet, self).get_urlpatterns(api_path=api_path)
-
- patterns.append( self.detail_url("attributes/$", {"get": "get_attributes", "post": "add_attribute"}, "attributes") )
- patterns.append( self.detail_url("attributes/(?P<attribute>[0-9]+)/$", {"get": "get_attribute", "put": "set_attribute", "delete": "delete_attribute"}, "attribute") )
-
- return patterns
-
- def get_attributes(self, request, pk=None):
- svc = self.get_object()
- return Response(ServiceAttributeSerializer(svc.serviceattributes.all(), many=True).data)
-
- def add_attribute(self, request, pk=None):
- svc = self.get_object()
- ser = ServiceAttributeSerializer(data=request.data)
- ser.is_valid(raise_exception = True)
- att = ServiceAttribute(service=svc, **ser.validated_data)
- att.save()
- return Response(ServiceAttributeSerializer(att).data)
-
- def get_attribute(self, request, pk=None, attribute=None):
- svc = self.get_object()
- att = ServiceAttribute.objects.get(pk=attribute)
- return Response(ServiceAttributeSerializer(att).data)
-
- def set_attribute(self, request, pk=None, attribute=None):
- svc = self.get_object()
- att = ServiceAttribute.objects.get(pk=attribute)
- ser = ServicettributeSerializer(att, data=request.data)
- ser.is_valid(raise_exception = True)
- att.name = ser.validated_data.get("name", att.name)
- att.value = ser.validated_data.get("value", att.value)
- att.save()
- return Response(ServiceAttributeSerializer(att).data)
-
- def delete_attribute(self, request, pk=None, attribute=None):
- att = ServiceAttribute.objects.get(pk=attribute)
- att.delete()
- return Response(status=status.HTTP_204_NO_CONTENT)
-
-
-
-
-
-
diff --git a/xos/api/tenant/onos/app.py b/xos/api/tenant/onos/app.py
deleted file mode 100644
index a93fa0d..0000000
--- a/xos/api/tenant/onos/app.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from rest_framework.decorators import api_view
-from rest_framework.response import Response
-from rest_framework.reverse import reverse
-from rest_framework import serializers
-from rest_framework import generics
-from rest_framework import status
-from core.models import *
-from django.forms import widgets
-from services.onos.models import ONOSService, ONOSApp
-from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
-from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
-
-def get_default_onos_service():
- onos_services = ONOSService.objects.all()
- if onos_services:
- return onos_services[0].id
- return None
-
-class ONOSAppSerializer(PlusModelSerializer):
- id = ReadOnlyField()
- name = serializers.CharField()
- dependencies = serializers.CharField()
-
- humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
- class Meta:
- model = ONOSApp
- fields = ('humanReadableName', 'id', 'name', 'dependencies')
-
- def getHumanReadableName(self, obj):
- return obj.__unicode__()
-
-class TenantAttributeSerializer(serializers.Serializer):
- id = ReadOnlyField()
- name = serializers.CharField(required=False)
- value = serializers.CharField(required=False)
-
-class ONOSAppViewSet(XOSViewSet):
- base_name = "app"
- method_name = "app"
- method_kind = "viewset"
- serializer_class = ONOSAppSerializer
-
- custom_serializers = {"set_attribute": TenantAttributeSerializer}
-
- @classmethod
- def get_urlpatterns(self, api_path="^"):
- patterns = super(ONOSAppViewSet, self).get_urlpatterns(api_path=api_path)
-
- patterns.append( self.detail_url("attributes/$", {"get": "get_attributes", "post": "add_attribute"}, "attributes") )
- patterns.append( self.detail_url("attributes/(?P<attribute>[0-9]+)/$", {"get": "get_attribute", "put": "set_attribute", "delete": "delete_attribute"}, "attribute") )
-
- return patterns
-
- def get_queryset(self):
- queryset = ONOSApp.objects.all()
-
- # Since name isn't a real database field of the Tenant object, we have
- # to go through some extra work...
- name = self.request.query_params.get('name', None)
- if name is not None:
- ids = [x.id for x in queryset.all() if x.name == name]
- return queryset.filter(id__in=ids)
-
- return queryset
-
- def get_attributes(self, request, pk=None):
- app = self.get_object()
- qs = app.tenantattributes.all()
- name = self.request.query_params.get('attribute_name', None)
- if name is not None:
- qs = qs.filter(name=name)
- return Response(TenantAttributeSerializer(qs, many=True).data)
-
- def add_attribute(self, request, pk=None):
- app = self.get_object()
- ser = TenantAttributeSerializer(data=request.data)
- ser.is_valid(raise_exception = True)
- att = TenantAttribute(tenant=app, **ser.validated_data)
- att.save()
- return Response(TenantAttributeSerializer(att).data)
-
- def get_attribute(self, request, pk=None, attribute=None):
- app = self.get_object()
- att = TenantAttribute.objects.get(pk=attribute)
- return Response(TenantAttributeSerializer(att).data)
-
- def set_attribute(self, request, pk=None, attribute=None):
- app = self.get_object()
- att = TenantAttribute.objects.get(pk=attribute)
- ser = TenantAttributeSerializer(att, data=request.data)
- ser.is_valid(raise_exception = True)
- att.name = ser.validated_data.get("name", att.name)
- att.value = ser.validated_data.get("value", att.value)
- att.save()
- return Response(TenantAttributeSerializer(att).data)
-
- def delete_attribute(self, request, pk=None, attribute=None):
- att = TenantAttribute.objects.get(pk=attribute)
- att.delete()
- return Response(status=status.HTTP_204_NO_CONTENT)
-
-
-
-
-
-
diff --git a/xos/attic/header.py b/xos/attic/header.py
index 33498dd..e3ab236 100644
--- a/xos/attic/header.py
+++ b/xos/attic/header.py
@@ -1,5 +1,5 @@
from django.db import models
-from core.models import Service, XOSBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor
+from core.models import Service, XOSBase, Slice, Instance, ServiceInstance, Node, Image, User, Flavor
from core.models.xosbase import StrippedCharField
import os
from django.db import models, transaction
diff --git a/xos/attic/onosapp_model.py b/xos/attic/onosapp_model.py
index a294f2d..8ac7d9e 100644
--- a/xos/attic/onosapp_model.py
+++ b/xos/attic/onosapp_model.py
@@ -1,17 +1,6 @@
def __init__(self, *args, **kwargs):
onos_services = ONOSService.objects.all()
if onos_services:
- self._meta.get_field("provider_service").default = onos_services[0].id
+ self._meta.get_field("owner").default = onos_services[0].id
super(ONOSApp, self).__init__(*args, **kwargs)
-def save(self, *args, **kwargs):
- if not self.creator:
- if not getattr(self, "caller", None):
- # caller must be set when creating a vCPE since it creates a slice
- raise XOSProgrammingError("ONOSApp's self.caller was not set")
- self.creator = self.caller
- if not self.creator:
- raise XOSProgrammingError("ONOSApp's self.creator was not set")
-
- super(ONOSApp, self).save(*args, **kwargs)
-
diff --git a/xos/header.py b/xos/header.py
index 33498dd..e3ab236 100755
--- a/xos/header.py
+++ b/xos/header.py
@@ -1,5 +1,5 @@
from django.db import models
-from core.models import Service, XOSBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor
+from core.models import Service, XOSBase, Slice, Instance, ServiceInstance, Node, Image, User, Flavor
from core.models.xosbase import StrippedCharField
import os
from django.db import models, transaction
diff --git a/xos/onos-onboard.yaml b/xos/onos-onboard.yaml
index 6f59f10..2670375 100644
--- a/xos/onos-onboard.yaml
+++ b/xos/onos-onboard.yaml
@@ -18,8 +18,6 @@
admin_template: templates/onosadmin.html
#tosca_custom_types: exampleservice.yaml
tosca_resource: tosca/resources/onosservice.py, tosca/resources/onosapp.py
- rest_service: api/service/onos.py
- rest_tenant: subdirectory:onos api/tenant/onos/app.py
private_key: file:///opt/xos/key_import/onos_rsa
public_key: file:///opt/xos/key_import/onos_rsa.pub
diff --git a/xos/onos.xproto b/xos/onos.xproto
index 24345ea..2481a5a 100644
--- a/xos/onos.xproto
+++ b/xos/onos.xproto
@@ -2,13 +2,11 @@
option name="onos";
option verbose_name="ONOS Service";
-message ONOSApp (Tenant){
+message ONOSApp (ServiceInstance){
optional string install_dependencies = 1 [db_index = False, null = True, blank = True];
optional string dependencies = 2 [db_index = False, null = True, blank = True];
- optional manytoone creator->User:onos_apps = 3 [db_index = True, null = True, blank = True];
}
-
message ONOSService (Service){
optional string rest_hostname = 1 [db_index = False, max_length = 255, null = True, content_type = "stripped", blank = True];
required int32 rest_port = 2 [default = 8181, null = False, db_index = False, blank = False];
diff --git a/xos/synchronizer/steps/sync_onosapp.py b/xos/synchronizer/steps/sync_onosapp.py
index ae9c5d7..e26cc1e 100644
--- a/xos/synchronizer/steps/sync_onosapp.py
+++ b/xos/synchronizer/steps/sync_onosapp.py
@@ -42,10 +42,10 @@
return None
def get_onos_service(self, o):
- if not o.provider_service:
+ if not o.owner:
return None
- onoses = ONOSService.objects.filter(id=o.provider_service.id)
+ onoses = ONOSService.objects.filter(id=o.owner.id)
if not onoses:
return None
@@ -115,7 +115,7 @@
# Combine the service attributes with the tenant attributes. Tenant
# attribute can override service attributes.
- attrs = o.provider_service.serviceattribute_dict
+ attrs = o.owner.serviceattribute_dict
attrs.update(o.tenantattribute_dict)
ordered_attrs = attrs.keys()
diff --git a/xos/tosca/resources/onosapp.py b/xos/tosca/resources/onosapp.py
index 39b3a2b..005e345 100644
--- a/xos/tosca/resources/onosapp.py
+++ b/xos/tosca/resources/onosapp.py
@@ -1,5 +1,5 @@
from xosresource import XOSResource
-from core.models import User, TenantAttribute, Service
+from core.models import User, ServiceInstanceAttribute, Service, ServiceInstanceLink
from services.onos.models import ONOSApp, ONOSService
class XOSONOSApp(XOSResource):
@@ -13,24 +13,14 @@
# provider_service is mandatory and must be the ONOS Service
provider_name = self.get_requirement("tosca.relationships.TenantOfService", throw_exception=throw_exception)
if provider_name:
- args["provider_service"] = self.get_xos_object(ONOSService, throw_exception=throw_exception, name=provider_name)
-
- # subscriber_service is optional and can be any service
- subscriber_name = self.get_requirement("tosca.relationships.UsedByService", throw_exception=False)
- if subscriber_name:
- args["subscriber_service"] = self.get_xos_object(Service, throw_exception=throw_exception, name=subscriber_name)
+ args["owner"] = self.get_xos_object(ONOSService, throw_exception=throw_exception, name=provider_name)
return args
- def get_existing_objs(self):
- objs = ONOSApp.objects.all()
- objs = [x for x in objs if x.name == self.obj_name]
- return objs
-
def set_tenant_attr(self, obj, prop_name, value):
value = self.try_intrinsic_function(value)
if value:
- attrs = TenantAttribute.objects.filter(tenant=obj, name=prop_name)
+ attrs = ServiceInstanceAttribute.objects.filter(service_instance=obj, name=prop_name)
if attrs:
attr = attrs[0]
if attr.value != value:
@@ -39,7 +29,7 @@
attr.save()
else:
self.info("adding attribute %s" % prop_name)
- ta = TenantAttribute(tenant=obj, name=prop_name, value=value)
+ ta = ServiceInstanceAttribute(service_instance=obj, name=prop_name, value=value)
ta.save()
def postprocess(self, obj):
@@ -55,5 +45,14 @@
elif k == "autogenerate":
self.set_tenant_attr(obj, k, v)
+ # subscriber_service is optional and can be any service
+ subscriber_name = self.get_requirement("tosca.relationships.UsedByService", throw_exception=False)
+ if subscriber_name:
+ sub_serv = self.get_xos_object(Service, throw_exception=True, name=subscriber_name)
+ existing_links = ServiceInstanceLink.objects.filter(provider_service_instance_id = obj.id, subscriber_service_id = sub_serv.id)
+ if not existing_links:
+ link = ServiceInstanceLink(provider_service_instance = obj, subscriber_service = sub_serv)
+ link.save()
+
def can_delete(self, obj):
return super(XOSONOSApp, self).can_delete(obj)