Merge branch 'AddVPNService' of github.com:jermowery/xos into AddVPNService
diff --git a/xos/core/admin.py b/xos/core/admin.py
index 675b8c2..ad49cec 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -270,6 +270,9 @@
def backend_status_text(self, obj):
return mark_safe(backend_text(obj))
+ def script_link(self, obj):
+ return mark_safe('<a href="%s" target="_blank">Script link</a>' % obj.file_name)
+
def backend_status_icon(self, obj):
return mark_safe(backend_icon(obj))
backend_status_icon.short_description = ""
@@ -494,7 +497,7 @@
class SiteHostsUsersInline(SiteInline):
def queryset(self, request):
- return Site.select_by_user(request.user).filter(hosts_users=True)
+ return Site.select_by_user(request.user).filter(hosts_users=True)
class UserInline(XOSTabularInline):
model = User
@@ -571,7 +574,7 @@
kwargs['queryset'] = Service.select_by_user(request.user)
if db_field.name == 'user':
kwargs['queryset'] = User.select_by_user(request.user)
- return super(ServicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
+ return super(ServicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
def queryset(self, request):
return ServicePrivilege.select_by_user(request.user)
@@ -803,12 +806,12 @@
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
obj.save_by_user(request.user)
-
+
def delete_model(self, request, obj):
obj.delete_by_user(request.user)
def queryset(self, request):
- return Controller.select_by_user(request.user)
+ return Controller.select_by_user(request.user)
@property
def suit_form_tabs(self):
@@ -1001,11 +1004,11 @@
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
- obj.save_by_user(request.user)
+ obj.save_by_user(request.user)
def delete_model(self, request, obj):
obj.delete_by_user(request.user)
-
+
class SitePrivilegeAdmin(XOSBaseAdmin):
fieldList = ['backend_status_text', 'user', 'site', 'role']
@@ -1103,7 +1106,7 @@
('slicenetworks','Networks'),
('sliceprivileges','Privileges'),
('instances','Instances'),
- #('reservations','Reservations'),
+ #('reservations','Reservations'),
('tags','Tags'),
]
@@ -1112,7 +1115,7 @@
tabs.append( ('admin-only', 'Admin-Only') )
return tabs
-
+
def add_view(self, request, form_url='', extra_context=None):
# Ugly hack for CORD
self.inlines = self.normal_inlines
@@ -1209,7 +1212,7 @@
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'slice':
kwargs['queryset'] = Slice.select_by_user(request.user)
-
+
if db_field.name == 'user':
kwargs['queryset'] = User.select_by_user(request.user)
@@ -1589,12 +1592,12 @@
login_details_fields.remove('profile')
#if len(request.user.siteprivileges.filter(role__role = 'pi')) > 0:
# only admins and pis can change a user's site
- # self.readonly_fields = ('backend_status_text', 'site')
+ # self.readonly_fields = ('backend_status_text', 'site')
self.fieldsets = (
('Login Details', {'fields': login_details_fields, 'classes':['suit-tab suit-tab-general']}),
('Contact Information', {'fields': self.fieldListContactInfo, 'classes':['suit-tab suit-tab-contact']}),
)
- return super(UserAdmin, self).get_form(request, obj, **kwargs)
+ return super(UserAdmin, self).get_form(request, obj, **kwargs)
class ControllerDashboardViewInline(XOSTabularInline):
model = ControllerDashboardView
@@ -2067,7 +2070,7 @@
# unregister the Group model from admin.
#admin.site.unregister(Group)
-# When debugging it is often easier to see all the classes, but for regular use
+# When debugging it is often easier to see all the classes, but for regular use
# only the top-levels should be displayed
showAll = False
@@ -2103,4 +2106,3 @@
admin.site.register(TenantRootRole, TenantRootRoleAdmin)
admin.site.register(TenantAttribute, TenantAttributeAdmin)
# admin.site.register(Container, ContainerAdmin)
-
diff --git a/xos/observers/vpn/steps/sync_vpntenant.py b/xos/observers/vpn/steps/sync_vpntenant.py
index c7c3c9d..31500d3 100644
--- a/xos/observers/vpn/steps/sync_vpntenant.py
+++ b/xos/observers/vpn/steps/sync_vpntenant.py
@@ -23,7 +23,7 @@
objs = VPNTenant.get_tenant_objects().filter(
Q(enacted__lt=F('updated')) | Q(enacted=None), Q(lazy_blocked=False))
for tenant in objs:
- tenant.client_conf = self.generate_client_conf(tenant)
+ self.create_client_script(tenant)
else:
objs = VPNTenant.get_deleted_tenant_objects()
@@ -36,6 +36,25 @@
"server_address": o.server_address,
"client_address": o.client_address}
+ def create_client_script(self, tenant):
+ script = open("/opt/xos/core/" + tenant.file_name, 'w')
+ # write the key portion
+ script.write("printf \"")
+ for line in tenant.server_key.splitlines():
+ script.write(line + r"\n")
+ script.write("\" > static.key\n")
+ # write the configuration portion
+ script.write("printf \"")
+ for line in self.generate_client_conf(tenant).splitlines():
+ script.write(line + r"\n")
+ script.write("\" > client.conf\n")
+ # make sure openvpn is installed
+ script.write("apt-get update\n")
+ script.write("apt-get install openvpn\n")
+ script.write("openvpn client.conf &")
+ # close the script
+ script.close()
+
def generate_client_conf(self, tenant):
"""str: Generates the client configuration to use to connect to this VPN server.
diff --git a/xos/services/vpn/admin.py b/xos/services/vpn/admin.py
index ceb59dc..67943b8 100644
--- a/xos/services/vpn/admin.py
+++ b/xos/services/vpn/admin.py
@@ -1,4 +1,4 @@
-
+import time
from subprocess import PIPE, Popen
from core.admin import ReadOnlyAwareAdmin, SliceInline
@@ -56,20 +56,20 @@
"""
creator = forms.ModelChoiceField(queryset=User.objects.all())
- server_key = forms.CharField(required=False, widget=forms.Textarea)
- client_conf = forms.CharField(required=False, widget=forms.Textarea)
+ server_key = forms.CharField(required=True, widget=forms.Textarea)
server_address = forms.GenericIPAddressField(
protocol='IPv4', required=True)
client_address = forms.GenericIPAddressField(
protocol='IPv4', required=True)
is_persistent = forms.BooleanField(required=False)
can_view_subnet = forms.BooleanField(required=False)
+ file_name = forms.CharField(required=True)
def __init__(self, *args, **kwargs):
super(VPNTenantForm, self).__init__(*args, **kwargs)
self.fields['kind'].widget.attrs['readonly'] = True
self.fields['server_key'].widget.attrs['readonly'] = True
- self.fields['client_conf'].widget.attrs['readonly'] = True
+ self.fields['file_name'].widget.attrs['readonly'] = True
self.fields[
'provider_service'].queryset = VPNService.get_service_objects().all()
@@ -78,7 +78,6 @@
if self.instance:
self.fields['creator'].initial = self.instance.creator
self.fields['server_key'].initial = self.instance.server_key
- self.fields['client_conf'].initial = self.instance.client_conf
self.fields[
'server_address'].initial = self.instance.server_address
self.fields[
@@ -86,6 +85,7 @@
self.fields['is_persistent'].initial = self.instance.is_persistent
self.fields[
'can_view_subnet'].initial = self.instance.can_view_subnet
+ self.fields['file_name'].initial = self.instance.file_name
if (not self.instance) or (not self.instance.pk):
self.fields['creator'].initial = get_request().user
@@ -94,6 +94,7 @@
self.fields['client_address'].initial = "10.8.0.2"
self.fields['is_persistent'].initial = True
self.fields['can_view_subnet'].initial = False
+ self.fields['file_name'].initial = "/static/vpn/" + time.time() + ".vpn"
if VPNService.get_service_objects().exists():
self.fields["provider_service"].initial = VPNService.get_service_objects().all()[
0]
@@ -104,10 +105,12 @@
self.instance.server_address = self.cleaned_data.get("server_address")
self.instance.client_address = self.cleaned_data.get("client_address")
self.instance.is_persistent = self.cleaned_data.get('is_persistent')
+ self.instance.file_name = self.cleaned_data.get('file_name')
self.instance.can_view_subnet = self.cleaned_data.get(
'can_view_subnet')
return super(VPNTenantForm, self).save(commit=commit)
+
def generate_VPN_key(self):
"""str: Generates a VPN key using the openvpn command."""
proc = Popen("openvpn --genkey --secret /dev/stdout",
@@ -125,11 +128,11 @@
list_display_links = ('id', 'backend_status_icon', 'instance')
fieldsets = [(None, {'fields': ['backend_status_text', 'kind',
'provider_service', 'instance', 'creator',
- 'server_key', 'client_conf',
+ 'server_key', 'file_name', 'script_link',
'server_address', 'client_address',
'is_persistent', 'can_view_subnet'],
'classes': ['suit-tab suit-tab-general']})]
- readonly_fields = ('backend_status_text', 'instance')
+ readonly_fields = ('backend_status_text', 'instance', 'script_link')
form = VPNTenantForm
suit_form_tabs = (('general', 'Details'),)
diff --git a/xos/services/vpn/models.py b/xos/services/vpn/models.py
index 8b2c5d8..2cdb5b9 100644
--- a/xos/services/vpn/models.py
+++ b/xos/services/vpn/models.py
@@ -27,11 +27,11 @@
sync_attributes = ("nat_ip", "nat_mac",)
default_attributes = {'server_key': 'Error key not found',
- 'client_conf': 'Configuration not found',
'server_address': '10.8.0.1',
'client_address': '10.8.0.2',
'can_view_subnet': False,
- 'is_persistent': True}
+ 'is_persistent': True,
+ 'file_name': 'Not found'}
def __init__(self, *args, **kwargs):
vpn_services = VPNService.get_service_objects().all()
@@ -115,17 +115,6 @@
self.set_attribute("client_address", value)
@property
- def client_conf(self):
- """str: The client configuration for the client to connect to this server."""
- return self.get_attribute(
- "client_conf",
- self.default_attributes['client_conf'])
-
- @client_conf.setter
- def client_conf(self, value):
- self.set_attribute("client_conf", value)
-
- @property
def is_persistent(self):
"""bool: True if the VPN connection is persistence, false otherwise."""
return self.get_attribute(
@@ -147,6 +136,14 @@
def can_view_subnet(self, value):
self.set_attribute("can_view_subnet", value)
+ @property
+ def file_name(self):
+ self.get_attribute("file_name", self.default_attributes['file_name'])
+
+ @file_name.setter
+ def file_name(self, value):
+ self.set_attribute('file_name', value)
+
def model_policy_vpn_tenant(pk):
"""Manages the contain for the VPN Tenant."""