Merge pick up, tweaked role/site/plcore_base or os_manager path when OpenStack not present
diff --git a/planetstack/core/admin.py b/planetstack/core/admin.py
index 6a8b71e..c9bba2c 100644
--- a/planetstack/core/admin.py
+++ b/planetstack/core/admin.py
@@ -30,8 +30,10 @@
class SliverInline(admin.TabularInline):
model = Sliver
- fields = ['ip', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
+ fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
extra = 0
+ #readonly_fields = ['ip', 'instance_name', 'image']
+ readonly_fields = ['ip', 'instance_name']
class SiteInline(admin.TabularInline):
model = Site
@@ -57,9 +59,13 @@
model = Node
extra = 0
-class PlainTextWidget(forms.Widget):
- def render(self, _name, value, attrs):
- return mark_safe(value) if value is not None else ''
+class PlainTextWidget(forms.HiddenInput):
+ input_type = 'hidden'
+
+ def render(self, name, value, attrs=None):
+ if value is None:
+ value = ''
+ return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
class PlanetStackBaseAdmin(admin.ModelAdmin):
save_on_top = False
@@ -68,15 +74,17 @@
"""Attach client connection to openstack on delete() and save()"""
def save_model(self, request, obj, form, change):
- auth = request.session.get('auth', {})
- #auth['tenant'] = request.user.site.login_base
- obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+ if request.user.site:
+ auth = request.session.get('auth', {})
+ auth['tenant'] = request.user.site.login_base
+ obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.save()
def delete_model(self, request, obj):
- auth = request.session.get('auth', {})
- #auth['tenant'] = request.user.site.login_base
- obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
+ if request.user.site:
+ auth = request.session.get('auth', {})
+ auth['tenant'] = request.user.site.login_base
+ obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.delete()
class RoleAdmin(OSModelAdmin):
@@ -125,7 +133,8 @@
continue
# give inline object access to driver and caller
auth = request.session.get('auth', {})
- auth['tenant'] = request.user.site.login_base
+ if request.user.site:
+ auth['tenant'] = request.user.site.login_base
inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
yield inline.get_formset(request, obj)
@@ -140,6 +149,17 @@
inlines = [NodeInline, UserInline]
search_fields = ['name']
+ def queryset(self, request):
+ # admins can see all keys. Users can only see sites they belong to.
+ qs = super(SiteAdmin, self).queryset(request)
+ if not request.user.is_admin:
+ valid_sites = [request.user.site.login_base]
+ roles = request.user.get_roles()
+ for tenant_list in roles.values():
+ valid_sites.extend(tenant_list)
+ qs = qs.filter(login_base__in=valid_sites)
+ return qs
+
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
@@ -157,6 +177,20 @@
]
list_display = ('user', 'site', 'role')
+ def queryset(self, request):
+ # admins can see all privileges. Users can only see privileges at sites
+ # where they have the admin role.
+ qs = super(SitePrivilegeAdmin, self).queryset(request)
+ if not request.user.is_admin:
+ roles = request.user.get_roles()
+ tenants = []
+ for (role, tenant_list) in roles:
+ if role == 'admin':
+ tenants.extend(tenant_list)
+ valid_sites = Sites.objects.filter(login_base__in=tenants)
+ qs = qs.filter(site__in=valid_sites)
+ return qs
+
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
@@ -173,24 +207,34 @@
class KeyAdmin(OSModelAdmin):
fieldsets = [
- ('Key', {'fields': ['name', 'key', 'type', 'blacklisted']})
+ ('Key', {'fields': ['key', 'type', 'blacklisted']})
]
- list_display = ['name', 'key', 'type', 'blacklisted']
+ list_display = ['key', 'type', 'blacklisted']
- def get_queryset(self, request):
- # get keys user is allowed to see
- qs = super(KeyAdmin, self).get_queryset(request)
- if request.user.is_superuser:
- return qs
- # users can only see their own keys
- return qs.filter(user=request.user)
+ #def queryset(self, request):
+ # admins can see all keys. Users can only see their own key.
+ #if request.user.is_admin:
+ # qs = super(KeyAdmin, self).queryset(request)
+ #else:
+ # qs = Key.objects.filter(user=request.user)
+ #return qs
-
class SliceAdmin(OSModelAdmin):
fields = ['name', 'site', 'serviceClass', 'description', 'slice_url']
list_display = ('name', 'site','serviceClass', 'slice_url')
inlines = [SliverInline]
+ def queryset(self, request):
+ # admins can see all keys. Users can only see slices they belong to.
+ qs = super(SliceAdmin, self).queryset(request)
+ if not request.user.is_admin:
+ valid_slices = []
+ roles = request.user.get_roles()
+ for tenant_list in roles.values():
+ valid_slices.extend(tenant_list)
+ qs = qs.filter(name__in=valid_slices)
+ return qs
+
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
@@ -215,24 +259,19 @@
]
list_display = ('user', 'slice', 'role')
- def save_model(self, request, obj, form, change):
- # update openstack connection to use this site/tenant
- auth = request.session.get('auth', {})
- auth['tenant'] = obj.slice.name
- obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
- obj.save()
-
- def delete_model(self, request, obj):
- # update openstack connection to use this site/tenant
- auth = request.session.get('auth', {})
- auth['tenant'] = obj.slice.name
- obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
- obj.delete()
-
-
-class SubnetAdmin(PlanetStackBaseAdmin):
- fields = ['cidr', 'ip_version', 'start', 'end', 'slice']
- list_display = ('slice','cidr', 'start', 'end', 'ip_version')
+ def queryset(self, request):
+ # admins can see all memberships. Users can only see memberships of
+ # slices where they have the admin role.
+ qs = super(SliceMembershipAdmin, self).queryset(request)
+ if not request.user.is_admin:
+ roles = request.user.get_roles()
+ tenants = []
+ for (role, tenant_list) in roles:
+ if role == 'admin':
+ tenants.extend(tenant_list)
+ valid_slices = Slice.objects.filter(name__in=tenants)
+ qs = qs.filter(slice__in=valid_slices)
+ return qs
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
@@ -248,6 +287,7 @@
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.delete()
+
class ImageAdmin(admin.ModelAdmin):
fields = ['image_id', 'name', 'disk_format', 'container_format']
@@ -258,9 +298,9 @@
class SliverForm(forms.ModelForm):
class Meta:
+ model = Sliver
ip = forms.CharField(widget=PlainTextWidget)
instance_name = forms.CharField(widget=PlainTextWidget)
- model = Sliver
widgets = {
'ip': PlainTextWidget(),
'instance_name': PlainTextWidget(),
@@ -269,9 +309,40 @@
class SliverAdmin(PlanetStackBaseAdmin):
form = SliverForm
fieldsets = [
- ('Sliver', {'fields': ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
+ ('Sliver', {'fields': ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
]
- list_display = ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
+ list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
+
+ def queryset(self, request):
+ # admins can see all slivers. Users can only see slivers of
+ # the slices they belong to.
+ qs = super(SliverAdmin, self).queryset(request)
+ if not request.user.is_admin:
+ tenants = []
+ roles = request.user.get_roles()
+ for tenant_list in roles.values():
+ tenants.extend(tenant_list)
+ valid_slices = Slice.objects.filter(name__in=tenants)
+ qs = qs.filter(slice__in=valid_slices)
+ return qs
+
+ def get_formsets(self, request, obj=None):
+ # make some fields read only if we are updating an existing record
+ if obj == None:
+ #self.readonly_fields = ('ip', 'instance_name')
+ self.readonly_fields = ()
+ else:
+ self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
+
+ for inline in self.get_inline_instances(request, obj):
+ # hide MyInline in the add view
+ if obj is None:
+ continue
+ # give inline object access to driver and caller
+ auth = request.session.get('auth', {})
+ auth['tenant'] = obj.name # meed to connect using slice's tenant
+ inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
+ yield inline.get_formset(request, obj)
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
@@ -343,17 +414,17 @@
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
- list_display = ('email', 'site', 'firstname', 'lastname', 'last_login')
+ list_display = ('email', 'site', 'firstname', 'lastname', 'is_admin', 'last_login')
list_filter = ('site',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
- ('Personal info', {'fields': ('firstname','lastname','phone','site', 'key')}),
+ ('Personal info', {'fields': ('firstname','lastname','phone', 'is_admin', 'site', 'key')}),
#('Important dates', {'fields': ('last_login',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
- 'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2', 'key')}
+ 'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'is_admin', 'key','password1', 'password2')}
),
)
search_fields = ('email',)
@@ -377,8 +448,8 @@
#admin.site.register(SitePrivilege, SitePrivilegeAdmin)
admin.site.register(Slice, SliceAdmin)
#admin.site.register(SliceMembership, SliceMembershipAdmin)
-admin.site.register(Subnet, SubnetAdmin)
-#admin.site.register(Image, ImageAdmin)
+#admin.site.register(Subnet, SubnetAdmin)
+admin.site.register(Image, ImageAdmin)
#admin.site.register(Node, NodeAdmin)
admin.site.register(Sliver, SliverAdmin)
admin.site.register(Key, KeyAdmin)
diff --git a/planetstack/core/api/deployment_networks.py b/planetstack/core/api/deployment_networks.py
index 51fa03e..fcd2145 100644
--- a/planetstack/core/api/deployment_networks.py
+++ b/planetstack/core/api/deployment_networks.py
@@ -1,8 +1,6 @@
from types import StringTypes
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
from core.models import DeploymentNetwork
+from django.contrib.auth import authenticate
def _get_deployment_networks(filter):
if isinstance(filter, StringTypes) and filter.isdigit():
@@ -18,20 +16,23 @@
return deployment_networks
def add_deployment_network(auth, name):
- auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
deployment = DeploymentNetwork(name=name)
deployment.save()
return deployment
def delete_deployment_network(auth, filter={}):
- auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
deployments = _get_deployment_networks(filter)
for deployment in deployments:
deployment.delete()
return 1
def get_deployment_networks(auth, filter={}):
- auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
deployments = _get_deployment_networks(filter)
return deployments
diff --git a/planetstack/core/api/images.py b/planetstack/core/api/images.py
index c080a55..933216f 100644
--- a/planetstack/core/api/images.py
+++ b/planetstack/core/api/images.py
@@ -1,7 +1,5 @@
from types import StringTypes
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from django.contrib.auth import authenticate
from core.models import Image
def _get_images(filter):
@@ -26,7 +24,8 @@
return 1
def get_images(auth, filter={}):
- auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
images = _get_images(filter)
return images
diff --git a/planetstack/core/api/keys.py b/planetstack/core/api/keys.py
index e653690..3528cd3 100644
--- a/planetstack/core/api/keys.py
+++ b/planetstack/core/api/keys.py
@@ -1,8 +1,7 @@
from types import StringTypes
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
+from django.contrib.auth import authenticate
+from openstack.manager import OpenStackManager
from core.models import Key
-from core.api.auth import auth_check
from core.api.users import _get_users
@@ -20,14 +19,17 @@
return keys
def add_key(auth, fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+ manager = OpenStackManager(auth=auth, caller = user)
+
+ # look up user object
users = _get_users(fields.get('user'))
if users: fields['user'] = users[0]
+ # save
key = Key(**fields)
- nova_fields = {'name': key.name,
- 'key': key.key}
- nova_key = driver.create_keypair(**nova_fields)
- key.nkey_id = nova_key.id
+ key.os_manager = manager
key.save()
return key
@@ -35,15 +37,20 @@
return
def delete_key(auth, filter={}):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+ manager = OpenStackManager(auth=auth, caller = user)
+
keys = _get_keys(filter)
for key in keys:
- driver.delete_keypair(id=key.nkey_id)
+ key.os_manager = manager
key.delete()
return 1
def get_keys(auth, filter={}):
- client = auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
keys = _get_keys(filter)
return keys
diff --git a/planetstack/core/api/nodes.py b/planetstack/core/api/nodes.py
index 6514e54..4f7ceeb 100644
--- a/planetstack/core/api/nodes.py
+++ b/planetstack/core/api/nodes.py
@@ -1,7 +1,5 @@
from types import StringTypes
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from django.contrib.auth import authenticate
from core.models import Node
def _get_nodes(filter):
@@ -29,7 +27,8 @@
return
def get_nodes(auth, filter={}):
- auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
nodes = _get_nodes(filter)
return nodes
diff --git a/planetstack/core/api/roles.py b/planetstack/core/api/roles.py
index a799c01..4ea05c9 100644
--- a/planetstack/core/api/roles.py
+++ b/planetstack/core/api/roles.py
@@ -1,7 +1,6 @@
from types import StringTypes
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from django.contrib.auth import authenticate
+from openstack.manager import OpenStackManager
from core.models import Role
@@ -19,21 +18,27 @@
return roles
def add_role(auth, name):
- driver = OpenStackDriver(client = auth_check(auth))
- keystone_role = driver.create_role(name=name)
- role = Role(role_type=name, role_id=keystone_role.id)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+
+ role = Role(role_type=name)
+ role.os_manager = OpenStackManager(auth=auth, caller = user)
role.save()
return role
def delete_role(auth, filter={}):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
roles = _get_roles(filter)
for role in roles:
- driver.delete_role({'id': role.role_id})
+ auth['tenant'] = user.site.login_base
+ role.os_manager = OpenStackManager(auth=auth, caller = user)
role.delete()
return 1
def get_roles(auth, filter={}):
- client = auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
return _get_roles(filter)
diff --git a/planetstack/core/api/site_privileges.py b/planetstack/core/api/site_privileges.py
index 85a8a83..6d79701 100644
--- a/planetstack/core/api/site_privileges.py
+++ b/planetstack/core/api/site_privileges.py
@@ -1,8 +1,7 @@
from types import StringTypes
import re
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from django.contrib.auth import authenticate
+from openstack.manager import OpenStackManager
from core.models import SitePrivilege
from core.api.users import _get_users
from core.api.sites import _get_sites
@@ -23,7 +22,9 @@
return site_privileges
def add_site_privilege(auth, fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+
users = _get_user(fields.get('user'))
sites = _get_slice(fields.get('site'))
roles = _get_role(fields.get('role'))
@@ -32,13 +33,9 @@
if slices: fields['site'] = sites[0]
if roles: fields['role'] = roles[0]
+ auth['tenant'] = sites[0].login_base
site_privilege = SitePrivilege(**fields)
-
- # update nova role
- driver.add_user_role(site_privilege.user.kuser_id,
- site_privilege.site.tenant_id,
- site_privilege.role.name)
-
+ site_privilege.os_manager = OpenStackManager(auth=auth, caller = user)
site_privilege.save()
return site_privilege
@@ -46,17 +43,21 @@
return
def delete_site_privilege(auth, filter={}):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+ manager = OpenStackManager(auth=auth, caller = user)
+
site_privileges = _get_site_privileges(filter)
for site_privilege in site_privileges:
- driver.delete_user_role(kuser_id=site_privilege.user.id,
- tenant_id = site_privilege.site.tenant_id,
- role_name = site_privilege.role.name)
+ auth['tenant'] = user.site.login_base
+ site_privilege.os_manager = OpenStackManager(auth=auth, caller = user)
site_privilege.delete()
return 1
def get_site_privileges(auth, filter={}):
- client = auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
users = _get_users(filter.get('user'))
sites = _get_slices(filter.get('site'))
roles = _get_roles(filter.get('role'))
diff --git a/planetstack/core/api/sites.py b/planetstack/core/api/sites.py
index cfca6cf..123f139 100644
--- a/planetstack/core/api/sites.py
+++ b/planetstack/core/api/sites.py
@@ -1,10 +1,8 @@
from types import StringTypes
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from django.contrib.auth import authenticate
+from openstack.manager import OpenStackManager
from core.models import Site
-
def _get_sites(filter):
if isinstance(filter, StringTypes) and filter.isdigit():
filter = int(filter)
@@ -19,42 +17,42 @@
return sites
def add_site(auth, fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+
site = Site(**fields)
- nova_fields = {'tenant_name': site.login_base,
- 'description': site.name,
- 'enabled': site.enabled}
- tenant = driver.create_tenant(**nova_fields)
- site.tenant_id=tenant.id
+ site.os_manager = OpenStackManager(auth=auth, caller = user)
site.save()
return site
def update_site(auth, id, **fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+
sites = _get_sites(id)
if not sites:
return
site = Site[0]
- nova_fields = {}
- if 'description' in fields:
- nova_fields['description'] = fields['name']
- if 'enabled' in fields:
- nova_fields['enabled'] = fields['enabled']
- driver.update_tenant(site.tenant_id, **nova_fields)
+ site.os_manager = OpenStackManager(auth=auth, caller = user)
site.update(**fields)
return site
def delete_site(auth, filter={}):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
sites = _get_sites(id)
for site in sites:
- driver.delete_tenant(id=site.tenant_id)
+ site.os_manager = OpenStackManager(auth=auth, caller = user)
site.delete()
return 1
def get_sites(auth, filter={}):
- client = auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
sites = _get_sites(filter)
return sites
diff --git a/planetstack/core/api/slice_memberships.py b/planetstack/core/api/slice_memberships.py
index 77d79bf..3e25ae7 100644
--- a/planetstack/core/api/slice_memberships.py
+++ b/planetstack/core/api/slice_memberships.py
@@ -1,7 +1,6 @@
from types import StringTypes
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from django.contrib.auth import authenticate
+from openstack.manager import OpenStackManager
from core.models import SliceMembership
from core.api.users import _get_users
from core.api.slices import _get_slices
@@ -22,7 +21,9 @@
def add_slice_membership(auth, fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+
users = _get_users(fields.get('user'))
slices = _get_slices(fields.get('slice'))
roles = _get_roles(fields.get('role'))
@@ -32,12 +33,8 @@
if roles: fields['role'] = roles[0]
slice_membership = SliceMembership(**fields)
-
- # update nova role
- driver.add_user_role(slice_membership.user.user_id,
- slice_membership.slice.tenant_id,
- slice_membership.role.name)
-
+ auth['tenant'] = sites[0].login_base
+ slice_membership.os_manager = OpenStackManager(auth=auth, caller = user)
slice_membership.save()
return slice_membership
@@ -45,17 +42,19 @@
return
def delete_slice_membership(auth, filter={}):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+
slice_memberships = _get_slice_memberships(filter)
for slice_membership in slice_memberships:
- driver.delete_user_role(kuser_id=slice_membership.user.id,
- tenant_id = slice_membership.slice.tenant_id,
- role_name = slice_membership.role.name)
+ slice_membership.os_manager = OpenStackManager(auth=auth, caller = user)
slice_membership.delete()
return 1
def get_slice_memberships(auth, filter={}):
- client = auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
users = _get_users(fields.get('user'))
slices = _get_slices(fields.get('slice'))
roles = _get_roles(fields.get('role'))
diff --git a/planetstack/core/api/slices.py b/planetstack/core/api/slices.py
index f03dd6f..c9e94a2 100644
--- a/planetstack/core/api/slices.py
+++ b/planetstack/core/api/slices.py
@@ -1,9 +1,7 @@
import re
from types import StringTypes
from django.contrib.auth import authenticate
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from openstack.manager import OpenStackManager
from core.models import Slice
from core.api.sites import _get_sites
@@ -22,61 +20,44 @@
def add_slice(auth, fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+
login_base = fields['name'][:fields['name'].find('_')]
sites = _get_sites(login_base)
if sites: fields['site'] = sites[0]
slice = Slice(**fields)
-
- # create tenant
- nova_fields = {'tenant_name': slice.name,
- 'description': slice.description,
- 'enabled': slice.enabled}
- tenant = driver.create_tenant(**nova_fields)
- slice.tenant_id=tenant.id
-
- # create network
- network = driver.create_network(slice.name)
- slice.network_id = network['id']
-
- # create router
- router = driver.create_router(slice.name)
- slice.router_id = router['id']
-
+ slice.os_manager = OpenStackManager(auth=auth, caller = user)
slice.save()
return slice
def update_slice(auth, id, **fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+
slices = _get_slices(id)
if not slices:
return
-
- # update tenant
slice = slices[0]
- nova_fields = {}
- if 'name' in fields:
- nova_fields['tenant_name'] = fields['name']
- if 'description' in fields:
- nova_fields['description'] = fields['description']
- if 'enabled' in fields:
- nova_fields['enabled'] = fields['enabled']
- driver.update_tenant(slice.tenant_id, **nova_fields)
-
- # update db record
sites = _get_sites(fields.get('site'))
if sites: fields['site'] = sites[0]
- slice.update(**fields)
+
+ slice.os_manager = OpenStackManager(auth=auth, caller = user)
+ for (k,v) in fields.items():
+ setattr(slice, k, v)
+ slice.save()
return slice
def delete_slice(auth, filter={}):
- driver = OpenStackDriver(client = auth_check(auth))
- slices = _get_slices(id)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+ slices = _get_slices(filter)
for slice in slices:
- driver.delete_network(slice.network_id)
- driver.delete_router(slice.router_id)
- driver.delete_slice(id=slice.tenant_id)
+ slice.os_manager = OpenStackManager(auth=auth, caller = user)
slice.delete()
return 1
diff --git a/planetstack/core/api/slivers.py b/planetstack/core/api/slivers.py
index e3244a4..16a7e0b 100644
--- a/planetstack/core/api/slivers.py
+++ b/planetstack/core/api/slivers.py
@@ -1,15 +1,12 @@
from types import StringTypes
from django.contrib.auth import authenticate
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from openstack.manager import OpenStackManager
from core.models import Sliver, Slice
from core.api.images import _get_images
from core.api.keys import _get_keys
from core.api.slices import _get_slices
from core.api.deployment_networks import _get_deployment_networks
from core.api.nodes import _get_nodes
-
def _get_slivers(filter):
if isinstance(filter, StringTypes) and filter.isdigit():
@@ -25,21 +22,23 @@
return slivers
def add_sliver(auth, fields):
- driver = OpenStackDriver(client = auth_check(auth))
-
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+
images = _get_images(fields.get('image'))
- if images: fields['image'] = images[0]
keys = _get_keys(fields.get('key'))
- if keys: fields['key'] = keys[0]
slices = _get_slices(fields.get('slice'))
- if slices:
- fields['slice'] = slices[0]
deployment_networks = _get_deployment_networks(fields.get('deploymentNetwork'))
- if deployment_networks: fields['deploymentNetwork'] = deployment_networks[0]
nodes = _get_nodes(fields.get('node'))
+ if images: fields['image'] = images[0]
+ if keys: fields['key'] = keys[0]
+ if slices: fields['slice'] = slices[0]
+ if deployment_networks: fields['deploymentNetwork'] = deployment_networks[0]
if nodes: fields['node'] = nodes[0]
+
sliver = Sliver(**fields)
- sliver.driver = driver
+ auth['tenant'] = sliver.slice.name
+ sliver.os_manager = OpenStackManager(auth=auth, caller = user)
sliver.save()
return sliver
@@ -47,10 +46,12 @@
return
def delete_sliver(auth, filter={}):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
slivers = _get_slivers(filter)
for sliver in slivers:
- sliver.driver = driver
+ auth['tenant'] = sliver.slice.name
+ slice.os_manager = OpenStackManager(auth=auth, caller = user)
sliver.delete()
return 1
diff --git a/planetstack/core/api/users.py b/planetstack/core/api/users.py
index 3b157ac..08e851c 100644
--- a/planetstack/core/api/users.py
+++ b/planetstack/core/api/users.py
@@ -1,7 +1,6 @@
from types import StringTypes
-from openstack.client import OpenStackClient
-from openstack.driver import OpenStackDriver
-from core.api.auth import auth_check
+from django.contrib.auth import authenticate
+from openstack.manager import OpenStackManager
from core.models import User, Site
from core.api.sites import _get_sites
@@ -19,22 +18,22 @@
return users
def add_user(auth, fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+
sites = _get_sites(fields.get('site'))
if sites: fields['site'] = sites[0]
user = User(**fields)
- nova_fields = {'name': user.email[:user.email.find('@')],
- 'email': user.email,
- 'password': fields.get('password'),
- 'enabled': user.enabled}
- nova_user = driver.create_user(**nova_fields)
- #driver.add_user_user(user.id, user.site.tenant_id, 'user')
- user.kuser_id=nova_user.id
+ user.os_manager = OpenStackManager(auth=auth, caller = user)
user.save()
return user
def update_user(auth, id, **fields):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
+
users = User.objects.filter(id=id)
if not users:
return
@@ -48,22 +47,27 @@
nova_fields['password'] = fields['password']
if 'enabled' in fields:
nova_fields['enabled'] = fields['enabled']
- driver.update_user(user.kuser_id, **nova_fields)
sites = _get_sites(fields.get('site'))
if sites: fields['site'] = sites[0]
- user.update(**fields)
+ user.os_manager = OpenStackManager(auth=auth, caller = user)
+ for (k,v) in fields.items():
+ setattr(user, k, v)
+ user.save()
return user
def delete_user(auth, filter={}):
- driver = OpenStackDriver(client = auth_check(auth))
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
+ auth['tenant'] = user.site.login_base
users = _get_users(filter)
for user in users:
- driver.delete_user(id=user.kuser_id)
+ user.os_manager = OpenStackManager(auth=auth, caller = user)
user.delete()
return 1
def get_users(auth, filter={}):
- client = auth_check(auth)
+ user = authenticate(username=auth.get('username'),
+ password=auth.get('password'))
users = _get_users(filter)
return users
diff --git a/planetstack/core/models/key.py b/planetstack/core/models/key.py
index 98cfb9b..7a8b322 100644
--- a/planetstack/core/models/key.py
+++ b/planetstack/core/models/key.py
@@ -1,23 +1,29 @@
import os
from django.db import models
from core.models import PlCoreBase
+from openstack.manager import OpenStackManager
+
# Create your models here.
class Key(PlCoreBase):
- name = models.CharField(max_length=256, unique=True)
- nkey_id = models.CharField(max_length=256, unique=True)
+ name = models.CharField(max_length=256)
+ nkey_id = models.CharField(null=True, blank=True, max_length=256, unique=True)
key = models.CharField(max_length=512)
type = models.CharField(max_length=256)
blacklisted = models.BooleanField(default=False)
- def __unicode__(self): return u'%s' % (self.name)
+ def __unicode__(self): return u'%s' % (self.key)
def save(self, *args, **kwds):
- self.os_manager.save_key(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.save_key(self)
super(Key, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- self.os_manager.delete_key(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.delete_key(self)
super(Key, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/plcorebase.py b/planetstack/core/models/plcorebase.py
index 52aa0f7..ed7c3ff 100644
--- a/planetstack/core/models/plcorebase.py
+++ b/planetstack/core/models/plcorebase.py
@@ -1,5 +1,6 @@
import os
from django.db import models
+from django.forms.models import model_to_dict
class PlCoreBase(models.Model):
@@ -10,5 +11,36 @@
abstract = True
app_label = "core"
+ def __init__(self, *args, **kwargs):
+ super(PlCoreBase, self).__init__(*args, **kwargs)
+ self.__initial = self._dict
+
+ @property
+ def diff(self):
+ d1 = self.__initial
+ d2 = self._dict
+ diffs = [(k, (v, d2[k])) for k, v in d1.items() if v != d2[k]]
+ return dict(diffs)
+
+ @property
+ def has_changed(self):
+ return bool(self.diff)
+
+ @property
+ def changed_fields(self):
+ return self.diff.keys()
+
+ def get_field_diff(self, field_name):
+ return self.diff.get(field_name, None)
+
+ def save(self, *args, **kwargs):
+ super(PlCoreBase, self).save(*args, **kwargs)
+ self.__initial = self._dict
+
+ @property
+ def _dict(self):
+ return model_to_dict(self, fields=[field.name for field in
+ self._meta.fields])
+
diff --git a/planetstack/core/models/role.py b/planetstack/core/models/role.py
index b3611c1..e7d31b9 100644
--- a/planetstack/core/models/role.py
+++ b/planetstack/core/models/role.py
@@ -2,6 +2,7 @@
import datetime
from django.db import models
from core.models import PlCoreBase
+from openstack.manager import OpenStackManager
class Role(PlCoreBase):
@@ -13,10 +14,14 @@
def save(self, *args, **kwds):
- self.os_manager.save_role(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.save_role(self)
super(Role, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- self.os_manager.delete_role(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.delete_role(self)
super(Role, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/site.py b/planetstack/core/models/site.py
index ebf2ab9..11e6a28 100644
--- a/planetstack/core/models/site.py
+++ b/planetstack/core/models/site.py
@@ -2,11 +2,11 @@
from django.db import models
from core.models import PlCoreBase
from core.models import DeploymentNetwork
-
+from openstack.manager import OpenStackManager
class Site(PlCoreBase):
- tenant_id = models.CharField(max_length=200, help_text="Keystone tenant id")
+ tenant_id = models.CharField(null=True, blank=True, max_length=200, help_text="Keystone tenant id")
name = models.CharField(max_length=200, help_text="Name for this Site")
site_url = models.URLField(null=True, blank=True, max_length=512, help_text="Site's Home URL Page")
enabled = models.BooleanField(default=True, help_text="Status for this Site")
@@ -21,12 +21,16 @@
def __unicode__(self): return u'%s' % (self.name)
def save(self, *args, **kwds):
- self.os_manager.save_site(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.save_site(self)
super(Site, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- self.os_manager.delete_site(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.delete_site(self)
super(Site, self).delete(*args, **kwds)
@@ -39,11 +43,15 @@
def __unicode__(self): return u'%s %s %s' % (self.site, self.user, self.role)
def save(self, *args, **kwds):
- self.os_manager.driver.add_user_role(self.user.kuser_id, self.site.tenant_id, self.role.role_type)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.driver.add_user_role(self.user.kuser_id, self.site.tenant_id, self.role.role_type)
super(SitePrivilege, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- self.os_manager.driver.delete_user_role(self.user.kuser_id, self.site.tenant_id, self.role.role_type)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.driver.delete_user_role(self.user.kuser_id, self.site.tenant_id, self.role.role_type)
super(SitePrivilege, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/slice.py b/planetstack/core/models/slice.py
index 539be24..a4eb3a4 100644
--- a/planetstack/core/models/slice.py
+++ b/planetstack/core/models/slice.py
@@ -5,6 +5,7 @@
from core.models import User
from core.models import Role
from core.models import DeploymentNetwork
+from openstack.manager import OpenStackManager
# Create your models here.
@@ -12,14 +13,13 @@
tenant_id = models.CharField(max_length=200, help_text="Keystone tenant id")
name = models.CharField(unique=True, help_text="The Name of the Slice", max_length=80)
enabled = models.BooleanField(default=True, help_text="Status for this Slice")
- SLICE_CHOICES = (('plc', 'PLC'), ('delegated', 'Delegated'), ('controller','Controller'), ('none','None'))
- instantiation = models.CharField(help_text="The instantiation type of the slice", max_length=80, choices=SLICE_CHOICES)
omf_friendly = models.BooleanField()
description=models.TextField(blank=True,help_text="High level description of the slice and expected activities", max_length=1024)
slice_url = models.URLField(blank=True, max_length=512)
site = models.ForeignKey(Site, related_name='slices', help_text="The Site this Node belongs too")
- network_id = models.CharField(max_length=256, help_text="Quantum network")
- router_id = models.CharField(max_length=256, help_text="Quantum router id")
+ network_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum network")
+ router_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum router id")
+ subnet_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum subnet id")
SVC_CLASS_CHOICES = (('besteffort', 'Best Effort'), ('silver', 'Silver'), ('gold','Gold'))
serviceClass = models.CharField(verbose_name="Service Class",default="besteffort",help_text="The Service Class of this slice", max_length=30, choices=SVC_CLASS_CHOICES)
@@ -28,11 +28,15 @@
def __unicode__(self): return u'%s' % (self.name)
def save(self, *args, **kwds):
- self.os_manager.save_slice(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.save_slice(self)
super(Slice, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- self.os_manager.delete_slice(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.delete_slice(self)
super(Slice, self).delete(*args, **kwds)
class SliceMembership(PlCoreBase):
@@ -43,9 +47,13 @@
def __unicode__(self): return u'%s %s %s' % (self.slice, self.user, self.role)
def save(self, *args, **kwds):
- self.os_manager.driver.add_user_role(self.user.kuser_id, self.slice.tenant_id, self.role.role_type)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.driver.add_user_role(self.user.kuser_id, self.slice.tenant_id, self.role.role_type)
super(SliceMembership, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- self.os_manager.driver.delete_user_role(self.user.kuser_id, self.slice.tenant_id, self.role.role_type)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.driver.delete_user_role(self.user.kuser_id, self.slice.tenant_id, self.role.role_type)
super(SliceMembership, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/sliver.py b/planetstack/core/models/sliver.py
index 580c2af..8ebcbd4 100644
--- a/planetstack/core/models/sliver.py
+++ b/planetstack/core/models/sliver.py
@@ -8,10 +8,11 @@
from core.models import Node
from core.models import Site
from core.models import DeploymentNetwork
+from openstack.manager import OpenStackManager
# Create your models here.
class Sliver(PlCoreBase):
- instance_id = models.CharField(max_length=200, help_text="Nova instance id")
+ instance_id = models.CharField(null=True, blank=True, max_length=200, help_text="Nova instance id")
name = models.CharField(max_length=200, help_text="Sliver name")
instance_name = models.CharField(blank=True, null=True, max_length=200, help_text="OpenStack generated name")
ip = models.GenericIPAddressField(help_text="Sliver ip address", blank=True, null=True)
@@ -20,18 +21,21 @@
slice = models.ForeignKey(Slice, related_name='slivers')
node = models.ForeignKey(Node, related_name='slivers')
deploymentNetwork = models.ForeignKey(DeploymentNetwork, verbose_name='deployment', related_name='sliver_deploymentNetwork')
- numberCores = models.IntegerField(verbose_name="Number of Cores", help_text="Number of cores for sliver", default=2)
+ numberCores = models.IntegerField(verbose_name="Number of Cores", help_text="Number of cores for sliver", default=0)
def __unicode__(self): return u'%s' % (self.instance_name)
def save(self, *args, **kwds):
- if not self.slice.subnet.exists():
- raise exceptions.ValidationError, "Slice %s has no subnet" % self.slice.name
-
- self.os_manager.save_sliver(self)
+ if not self.name:
+ self.name = self.slice.name
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.save_sliver(self)
super(Sliver, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- self.os_manager.delete_sliver(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.delete_sliver(self)
super(Sliver, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/subnet.py b/planetstack/core/models/subnet.py
index cad9fea..37175ec 100644
--- a/planetstack/core/models/subnet.py
+++ b/planetstack/core/models/subnet.py
@@ -3,6 +3,7 @@
from django.db import models
from core.models import PlCoreBase
from core.models import Slice
+from openstack.manager import OpenStackManager
# Create your models here.
@@ -17,9 +18,13 @@
def __unicode__(self): return u'%s' % (self.slice.name)
def save(self, *args, **kwds):
- self.os_manager.save_subnet(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.save_subnet(self)
super(Subnet, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- self.os_manager.delete_subnet(self)
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
+ self.os_manager.delete_subnet(self)
super(Subnet, self).delete(*args, **kwds)
diff --git a/planetstack/core/models/user.py b/planetstack/core/models/user.py
index 6c776b1..38c0d89 100644
--- a/planetstack/core/models/user.py
+++ b/planetstack/core/models/user.py
@@ -1,5 +1,6 @@
import os
import datetime
+from collections import defaultdict
from django.db import models
from core.models import PlCoreBase
from core.models import Site
@@ -8,8 +9,6 @@
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
# Create your models here.
-has_openstack = False
-
class UserManager(BaseUserManager):
def create_user(self, email, firstname, lastname, password=None):
"""
@@ -57,7 +56,7 @@
db_index=True,
)
- kuser_id = models.CharField(help_text="keystone user id", max_length=200)
+ kuser_id = models.CharField(null=True, blank=True, help_text="keystone user id", max_length=200)
firstname = models.CharField(help_text="person's given name", max_length=200)
lastname = models.CharField(help_text="person's surname", max_length=200)
@@ -96,27 +95,31 @@
# Simplest possible answer: Yes, always
return True
- @property
- def is_staff(self):
- "Is the user a member of staff?"
- # Simplest possible answer: All admins are staff
- return self.is_admin
+ def get_roles(self):
+ from plstackapi.core.models.site import SitePrivilege
+ from plstackapi.core.models.slice import SliceMembership
+ site_privileges = SitePrivilege.objects.filter(user=self)
+ slice_memberships = SliceMembership.objects.filter(user=self)
+ roles = defaultdict(list)
+ for site_privilege in site_privileges:
+ roles[site_privilege.role.role_type].append(site_privilege.site.login_base)
+ for slice_membership in slice_memberships:
+ roles[slice_membership.role.role_type].append(slice_membership.slice.name)
+ return roles
def save(self, *args, **kwds):
- if has_openstack:
- if not hasattr(self, 'os_manager'):
- setattr(self, 'os_manager', OpenStackManager())
-
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
self.os_manager.save_user(self)
+
if not self.id:
self.set_password(self.password)
super(User, self).save(*args, **kwds)
def delete(self, *args, **kwds):
- if has_openstack:
- if not hasattr(self, 'os_manager'):
- setattr(self, 'os_manager', OpenStackManager())
-
+ if not hasattr(self, 'os_manager'):
+ setattr(self, 'os_manager', OpenStackManager())
self.os_manager.delete_user(self)
+
super(User, self).delete(*args, **kwds)
diff --git a/planetstack/core/serializers.py b/planetstack/core/serializers.py
index 55cf7c8..7c5dca9 100644
--- a/planetstack/core/serializers.py
+++ b/planetstack/core/serializers.py
@@ -53,7 +53,6 @@
id = serializers.Field()
site = serializers.HyperlinkedRelatedField(view_name='site-detail')
slivers = serializers.HyperlinkedRelatedField(view_name='sliver-detail')
- subnet= serializers.HyperlinkedRelatedField(view_name='subnet-detail')
class Meta:
model = Slice
fields = ('id',
@@ -61,12 +60,12 @@
'enabled',
'name',
'url',
- 'instantiation',
'omf_friendly',
'description',
'slice_url',
'network_id',
'router_id',
+ 'subnet_id',
'site',
'slivers',
'updated',
@@ -84,19 +83,6 @@
'slice',
'role')
-class SubnetSerializer(serializers.HyperlinkedModelSerializer):
- id = serializers.Field()
- slice = serializers.HyperlinkedRelatedField(view_name='slice-detail')
- class Meta:
- model = Subnet
- fields = ('id',
- 'subnet_id',
- 'cidr',
- 'ip_version',
- 'start',
- 'end',
- 'slice')
-
class SiteSerializer(serializers.HyperlinkedModelSerializer):
#Experimenting with whether to use ids, hyperlinks, or nested includes
@@ -200,7 +186,6 @@
SitePrivilege: SitePrivilegeSerializer,
Slice: SliceSerializer,
SliceMembership: SliceMembershipSerializer,
- Subnet: SubnetSerializer,
Node: NodeSerializer,
Sliver: SliverSerializer,
DeploymentNetwork: DeploymentNetworkSerializer,