CORD-2602 remove syndicate_storage service

Change-Id: Ida72dd3b312b0b16f7835620ac6504a5d85b23fc
diff --git a/xos/coreapi/app_list_builder.py b/xos/coreapi/app_list_builder.py
index 7bdec45..afa2ebf 100644
--- a/xos/coreapi/app_list_builder.py
+++ b/xos/coreapi/app_list_builder.py
@@ -32,8 +32,6 @@
             if (not fn.startswith(".")) and os.path.isdir(service_dir):
                 models_fn = os.path.join(service_dir, "models.py")
                 if os.path.exists(models_fn):
-                    if fn == "syndicate_storage":
-                        continue
                     app_names.append(fn)
 
         # Generate the migration list
diff --git a/xos/services/syndicate_storage/__init__.py b/xos/services/syndicate_storage/__init__.py
deleted file mode 100644
index d4e8062..0000000
--- a/xos/services/syndicate_storage/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
diff --git a/xos/services/syndicate_storage/admin.py b/xos/services/syndicate_storage/admin.py
deleted file mode 100644
index e56c9a8..0000000
--- a/xos/services/syndicate_storage/admin.py
+++ /dev/null
@@ -1,173 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-from django.contrib import admin
-
-from services.syndicate_storage.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 suit.widgets import LinkedSelect
-from core.admin import ReadOnlyAwareAdmin,ServiceAppAdmin,SliceInline,ServiceAttrAsTabInline,XOSBaseAdmin, XOSTabularInline
-from suit.widgets import LinkedSelect
-from django.core.exceptions import ValidationError, ObjectDoesNotExist
-
-class SyndicateAdmin(ReadOnlyAwareAdmin):
-   # Change the application breadcrumb to point to an RR Service if one is
-   # defined
-
-   change_form_template = "admin/change_form_bc.html"
-   change_list_template = "admin/change_list_bc.html"
-   custom_app_breadcrumb_name = "Syndicate_Storage"
-   @property
-   def custom_app_breadcrumb_url(self):
-       services = SyndicateService.objects.all()
-       if len(services)==1:
-           return "/admin/syndicate_storage/syndicateservice/%s/" % services[0].id
-       else:
-           return "/admin/syncdicate_storage/syndicateservice/"
-
-class SyndicateServiceAdmin(ServiceAppAdmin):
-    model = SyndicateService
-    verbose_name = "Syndicate Storage"
-    verbose_name_plural = "Syndicate Storage"
-    list_display = ("name","enabled")
-    fieldsets = [(None, {'fields': ['name','enabled','versionNumber', 'description',], 'classes':['suit-tab suit-tab-general']})]
-    inlines = [SliceInline,ServiceAttrAsTabInline]
-
-    user_readonly_fields = ['name','enabled','versionNumber','description']
-
-    suit_form_tabs =(('general', 'Syndicate Storage Details'),
-        ('administration', 'Administration'),
-        ('slices','Slices'),
-        ('serviceattrs','Additional Attributes'),
-    )
-
-    suit_form_includes = (('syndicateadmin.html', 'top', 'administration'),)
-
-
-class VolumeAccessRightInline(XOSTabularInline):
-    model = VolumeAccessRight
-    extra = 0
-    suit_classes = 'suit-tab suit-tab-volumeAccessRights'
-
-
-class VolumeSliceFormSet( forms.models.BaseInlineFormSet ):
-    # verify that our VolumeSlice is valid
-
-    @classmethod
-    def verify_unchanged( cls, volume_pk, slice_pk, field_name, new_value ):
-        vs = None
-        try:
-           vs = VolumeSlice.objects.get( volume_id=volume_pk, slice_id=slice_pk )
-        except ObjectDoesNotExist, dne:
-           return True, None
-
-        old_value = getattr( vs, field_name )
-        if old_value != new_value:
-            return False, old_value
-        else:
-            return True, None
-
-
-    def clean( self ):
-        for form in self.forms:
-            # check each inline's cleaned data, if it's valid
-            cleaned_data = None
-            try:
-                if form.cleaned_data:
-                    cleaned_data = form.cleaned_data
-            except AttributeError:
-                continue
-             
-            # verify that the ports haven't changed 
-            volume_pk = cleaned_data['volume_id'].pk
-            slice_pk = cleaned_data['slice_id'].pk
-           
-            if not cleaned_data.has_key('UG_portnum'):
-                raise ValidationError("Missing UG port number")
-
-            if not cleaned_data.has_key('RG_portnum'):
-                raise ValidationError("Missing RG port number")
-
-            rc1, old_peer_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'UG_portnum', cleaned_data['UG_portnum'] )
-            rc2, old_replicate_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'RG_portnum', cleaned_data['RG_portnum'] )
-
-            err1str = ""
-            err2str = ""
-            if not rc1:
-                err1str = "change %s back to %s" % (cleaned_data['UG_portnum'], old_peer_port)
-            if not rc2:
-                err2str = " and change %s back to %s" % (cleaned_data['RG_portnum'], old_replicate_port )
-
-            if not rc1 or not rc2:
-                raise ValidationError("At this time, port numbers cannot be changed once they are set. Please %s %s" % (err1str, err2str))
-            
-            
-
-class VolumeSliceInline(XOSTabularInline):
-    model = VolumeSlice
-    extra = 0
-    suit_classes = 'suit-tab suit-tab-volumeSlices'
-    fields = ['volume_id', 'slice_id', 'cap_read_data', 'cap_write_data', 'cap_host_data', 'UG_portnum', 'RG_portnum']
-
-    formset = VolumeSliceFormSet
-    
-    readonly_fields = ['credentials_blob']
- 
-
-class VolumeAdmin(SyndicateAdmin):
-    model = Volume
-   
-    def get_readonly_fields(self, request, obj=None ):
-       always_readonly = []
-       if obj == None:
-          # all fields are editable on add
-          return always_readonly
-
-       else:
-          # can't change owner, slice id, or block size on update
-          return ['blocksize', 'owner_id'] + always_readonly
-
-
-    list_display = ['name', 'owner_id']
-
-    detailsFieldList = ['name', 'owner_id', 'description','blocksize', 'private','archive', 'cap_read_data', 'cap_write_data', 'cap_host_data' ]
-
-    fieldsets = [
-        (None, {'fields': detailsFieldList, 'classes':['suit-tab suit-tab-general']}),
-    ]
-
-    inlines = [VolumeAccessRightInline, VolumeSliceInline]
-
-    user_readonly_fields = ['name','owner_id','description','blocksize','private', 'archive', 'cap_read_data', 'cap_write_data', 'cap_host_data']
-    
-    suit_form_tabs =(('general', 'Volume Details'),
-                     ('volumeSlices', 'Slices'),
-                     ('volumeAccessRights', 'Volume Access Rights'))
-    
-    def queryset(self, request):
-       # only show volumes that are public, or owned by the caller 
-       return Volume.select_by_user(request.user)
-    
-    
-# left panel:
-admin.site.register(SyndicateService, SyndicateServiceAdmin)
-admin.site.register(Volume, VolumeAdmin)
diff --git a/xos/services/syndicate_storage/migrations/__init__.py b/xos/services/syndicate_storage/migrations/__init__.py
deleted file mode 100644
index d4e8062..0000000
--- a/xos/services/syndicate_storage/migrations/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
diff --git a/xos/services/syndicate_storage/models.py b/xos/services/syndicate_storage/models.py
deleted file mode 100644
index 5b90d52..0000000
--- a/xos/services/syndicate_storage/models.py
+++ /dev/null
@@ -1,275 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-from core.models import User,Site,Service,XOSBase,Slice,SlicePrivilege
-import os
-from django.db import models
-from django.db.models import Q
-from django.forms.models import model_to_dict
-from django.core.exceptions import ValidationError, ObjectDoesNotExist
-
-# Create your models here.
-
-class SyndicateService(Service):
-    class Meta:
-        app_label = "syndicate_storage"
-        verbose_name = "Syndicate Service"
-        verbose_name_plural = "Syndicate Service"
-
-    def __unicode__(self):  return u'Syndicate Service'
-
-
-class SyndicatePrincipal(XOSBase):
-    class Meta:
-        app_label = "syndicate_storage"
-
-    # for now, this is a user email address 
-    principal_id = models.TextField(unique=True)
-    public_key_pem = models.TextField()
-    sealed_private_key = models.TextField()
-
-    def __unicode__self(self):  return "%s" % self.principal_id
-
-
-class Volume(XOSBase):
-    class Meta:
-        app_label = "syndicate_storage"
-
-    name = models.CharField(max_length=64, help_text="Human-readable, searchable name of the Volume")
-    
-    owner_id = models.ForeignKey(User, verbose_name='Owner')
-
-    description = models.TextField(null=True, blank=True,max_length=130, help_text="Human-readable description of what this Volume is used for.")
-    blocksize = models.PositiveIntegerField(help_text="Number of bytes per block.")
-    private = models.BooleanField(default=True, help_text="Indicates if the Volume is visible to users other than the Volume Owner and Syndicate Administrators.")
-    archive = models.BooleanField(default=False, help_text="Indicates if this Volume is read-only, and only an Aquisition Gateway owned by the Volume owner (or Syndicate admin) can write to it.")
-
-    cap_read_data = models.BooleanField(default=True, help_text="VM can read Volume data")
-    cap_write_data = models.BooleanField(default=True, help_text="VM can write Volume data")
-    cap_host_data = models.BooleanField(default=True, help_text="VM can host Volume data")
-    
-    slice_id = models.ManyToManyField(Slice, through="VolumeSlice")
-    
-    def __unicode__(self):  return self.name
- 
-    
-    @staticmethod
-    def select_by_user(user):
-        """
-        Only return Volumes accessible by the user.
-        Admin users can see everything.
-        """
-        if user.is_admin:
-            qs = Volume.objects.all()
-        else:
-            qs = Volume.objects.filter( Q(owner_id=user) | Q(private=False) )
-            
-        return qs
-
-
-class VolumeAccessRight(XOSBase):
-    class Meta:
-        app_label = "syndicate_storage"
-
-    owner_id = models.ForeignKey(User, verbose_name='user')
-    
-    volume = models.ForeignKey(Volume)
-
-    cap_read_data = models.BooleanField(default=True, help_text="VM can read Volume data")
-    cap_write_data = models.BooleanField(default=True, help_text="VM can write Volume data")
-    cap_host_data = models.BooleanField(default=True, help_text="VM can host Volume data")
-
-
-    def __unicode__(self):  return "%s-%s" % (self.owner_id.email, self.volume.name)
-
-
-class ObserverSecretValue( models.TextField ):
-    class Meta:
-        app_label = "syndicate_storage"
-    
-    __metaclass__ = models.SubfieldBase
-    
-    MAGIC_PREFIX = "$SECRET$:"
-    
-    @classmethod 
-    def is_encrypted( cls, secret_str ):
-       # all encrypted secrets start with MAGIC_PREFIX, which is NOT base64-encoded
-       return secret_str.startswith( cls.MAGIC_PREFIX )
-    
-    @classmethod 
-    def unserialize( cls, serialized_ciphertext ):
-       # strip prefix and return ciphertext 
-       return serialized_ciphertext[len(cls.MAGIC_PREFIX):]
-    
-    @classmethod 
-    def serialize( cls, ciphertext ):
-       # prepend a magic prefix so we know it's encrypted 
-       return cls.MAGIC_PREFIX + ciphertext
-    
-    def to_python( self, secret_str ):
-       """
-       Decrypt the value with the Observer key
-       """
-       
-       # is this in the clear?
-       if not ObserverSecretValue.is_encrypted( secret_str ):
-          # nothing to do
-          return secret_str
-       
-       # otherwise, decrypt it
-       from observers.syndicate import syndicatelib
-       
-       # get observer private key
-       config = syndicatelib.get_config()
-       
-       try:
-          observer_pkey_path = config.SYNDICATE_PRIVATE_KEY
-          observer_pkey_pem = syndicatelib.get_private_key_pem( observer_pkey_path )
-       except:
-          raise syndicatelib.SyndicateObserverError( "Internal Syndicate Observer error: failed to load Observer private key" )
-       
-       # deserialize 
-       secret_str = ObserverSecretValue.unserialize( secret_str )
-       
-       # decrypt
-       if secret_str is not None and len(secret_str) > 0:
-          
-          slice_secret = syndicatelib.decrypt_slice_secret( observer_pkey_pem, secret_str )
-          
-          if slice_secret is not None:
-             return slice_secret 
-          
-          else:
-             raise syndicatelib.SyndicateObserverError( "Internal Syndicate Observer error: failed to decrypt slice secret value" )
-       else:
-          return None
-       
-       
-    def pre_save( self, model_inst, add ):
-       """
-       Encrypt the value with the Observer key
-       """
-       
-       from observers.syndicate import syndicatelib 
-       
-       # get observer private key
-       config = syndicatelib.get_config()
-       
-       try:
-          observer_pkey_path = config.SYNDICATE_PRIVATE_KEY
-          observer_pkey_pem = syndicatelib.get_private_key_pem( observer_pkey_path )
-       except:
-          raise syndicatelib.SyndicateObserverError( "Internal Syndicate Observer error: failed to load Observer private key" )
-       
-       slice_secret = getattr(model_inst, self.attname )
-       
-       if slice_secret is not None:
-          
-          # encrypt it 
-          sealed_slice_secret = syndicatelib.encrypt_slice_secret( observer_pkey_pem, slice_secret )
-          
-          return ObserverSecretValue.serialize( sealed_slice_secret )
-       
-       else:
-          raise syndicatelib.SyndicateObserverError( "Internal Syndicate Observer error: No slice secret generated" )
-                                                    
-
-class SliceSecret(models.Model):        # NOTE: not a XOSBase
-    class Meta:
-       app_label = "syndicate_storage"
-    
-    slice_id = models.ForeignKey(Slice)
-    secret = ObserverSecretValue(blank=True, help_text="Shared secret between OpenCloud and this slice's Syndicate daemons.")
-    
-    def __unicode__(self):  return self.slice_id.name
- 
-    @staticmethod
-    def select_by_user(user):
-        """
-        Only return slice secrets for slices where this user has 'admin' role.
-        Admin users can see everything.
-        """
-        if user.is_admin:
-            qs = SliceSecret.objects.all()
-        else:
-            visible_slice_ids = [sp.slice.id for sp in SlicePrivilege.objects.filter(user=user,role__role='admin')]
-            qs = SliceSecret.objects.filter(slice_id__id__in=visible_slice_ids)
-            
-        return qs
- 
-
-class VolumeSlice(XOSBase):
-    class Meta:
-        app_label = "syndicate_storage"
-
-    volume_id = models.ForeignKey(Volume, verbose_name="Volume")
-    slice_id = models.ForeignKey(Slice, verbose_name="Slice")
-    
-    cap_read_data = models.BooleanField(default=True, help_text="VM can read Volume data")
-    cap_write_data = models.BooleanField(default=True, help_text="VM can write Volume data")
-    cap_host_data = models.BooleanField(default=True, help_text="VM can host Volume data")
-    
-    UG_portnum = models.PositiveIntegerField(help_text="User Gateway port.  Any port above 1024 will work, but it must be available slice-wide.", verbose_name="UG port")
-    RG_portnum = models.PositiveIntegerField(help_text="Replica Gateway port.  Any port above 1024 will work, but it must be available slice-wide.", verbose_name="RG port")
-    
-    credentials_blob = models.TextField(null=True, blank=True, help_text="Encrypted slice credentials, sealed with the slice secret.")
- 
-    def __unicode__(self):  return "%s-%s" % (self.volume_id.name, self.slice_id.name)
-
-    def clean(self):
-        """
-        Verify that our fields are in order:
-            * UG_portnum and RG_portnum have to be valid port numbers between 1025 and 65534
-            * UG_portnum and RG_portnum cannot be changed once set.
-            * UG_portnum and RG_portnum are unique
-        """
-
-        if self.UG_portnum == self.RG_portnum:
-            raise ValidationError( "UG and RG ports must be unique" )
-         
-        if self.UG_portnum < 1025 or self.UG_portnum > 65534:
-            raise ValidationError( "UG port number must be between 1025 and 65534" )
-
-        if self.RG_portnum < 1025 or self.RG_portnum > 65534:
-            raise ValidationError( "RG port number must be between 1025 and 65534" )
-         
-         
-    def save(self, *args, **kw):
-       """
-       Make sure a SliceSecret exists for this slice
-       """
-       
-       from observers.syndicate import syndicatelib
-       
-       # get observer private key
-       config = syndicatelib.get_config()
-       
-       try:
-          observer_pkey_path = config.SYNDICATE_PRIVATE_KEY
-          observer_pkey_pem = syndicatelib.get_private_key_pem( observer_pkey_path )
-       except:
-          raise syndicatelib.SyndicateObserverError( "Internal Syndicate Observer error: failed to load Observer private key" )
-       
-       # get or create the slice secret 
-       slice_secret = syndicatelib.get_or_create_slice_secret( observer_pkey_pem, None, slice_fk=self.slice_id )
-       
-       if slice_secret is None:
-          raise SyndicateObserverError( "Failed to get or create slice secret for %s" % self.slice_id.name )
-       
-       super(VolumeSlice, self).save(*args, **kw)
-       
-
-
diff --git a/xos/services/syndicate_storage/templates/syndicateadmin.html b/xos/services/syndicate_storage/templates/syndicateadmin.html
deleted file mode 100644
index de8fb4e..0000000
--- a/xos/services/syndicate_storage/templates/syndicateadmin.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-<!--
-Copyright 2017-present Open Networking Foundation
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-
-<div class = "left-nav">
-<ul>
-{% for admin in registered_admins %}
-    <li><a href="{{ admin.url }}">{{ admin.name }}</a></li>
-{% endfor %}
-</ul>
-</div>
-
-<!--
-<ul>
-<li><a href="/admin/syndicate_storage/volume/">Volumes</a></li>
-</ul>
--->
diff --git a/xos/tools/xos-manage b/xos/tools/xos-manage
index 8140b98..819c887 100755
--- a/xos/tools/xos-manage
+++ b/xos/tools/xos-manage
@@ -105,7 +105,7 @@
     mkdir -p $BACKUP_DIR
     FN="$BACKUP_DIR/dumpdata-`date +%Y-%m-%d_%H:%M:%S`.json"
     echo "Saving data to $FN"
-    python manage.py dumpdata core syndicate_storage -a --indent 4 > $FN
+    python manage.py dumpdata core -a --indent 4 > $FN
     if [[ ! -f $FN ]]; then
         echo "FAILED to create $FN"
         exit
@@ -135,7 +135,6 @@
 
 function makemigrations {
     python ./manage.py makemigrations core
-    python ./manage.py makemigrations syndicate_storage
 
     if [[ -e /opt/xos/xos/xosbuilder_migration_list ]]; then
         cat /opt/xos/xos/xosbuilder_migration_list | while read line; do
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index 1661cfc..9b8b6e8 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -169,13 +169,9 @@
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
-    # 'django.contrib.sites',
     'django.contrib.messages',
     'django_extensions',
     'core',
-    'services.syndicate_storage',
-    # 'geoposition',
-    # 'rest_framework_swagger',
 )
 
 # add services that were configured by xosbuilder to INSTALLED_APPS