Work on vpn view
diff --git a/views/ngXosViews/vpnDashboard/src/css/dev.css b/views/ngXosViews/vpnDashboard/src/css/dev.css
index 67c3992..4c504c9 100644
--- a/views/ngXosViews/vpnDashboard/src/css/dev.css
+++ b/views/ngXosViews/vpnDashboard/src/css/dev.css
@@ -9,3 +9,6 @@
     display: table-cell;
     padding: 5px;
 }
+.header {
+    font-weight: bold;
+}
diff --git a/views/ngXosViews/vpnDashboard/src/js/main.js b/views/ngXosViews/vpnDashboard/src/js/main.js
index b3b7f85..7a576df 100644
--- a/views/ngXosViews/vpnDashboard/src/js/main.js
+++ b/views/ngXosViews/vpnDashboard/src/js/main.js
@@ -12,18 +12,18 @@
   .state('vpnList', {
     url: '/',
     template: '<vpn-list></vpn-list>'
-  })
-  .state('clientScript', {
-    url: '/client/:tenantId',
-    template: '<client-script></client-script>'
   });
 })
+.config(($compileProvider) => {
+  $compileProvider.aHrefSanitizationWhitelist(
+    /^\s*(https?|ftp|mailto|tel|file|blob):/);
+})
 .service('Vpn', function($http, $q){
 
   this.getVpnTenants = () => {
     let deferred = $q.defer();
 
-    $http.get('/xoslib/vpntenants/')
+    $http.get('/xoslib/vpntenant/')
     .then((res) => {
       deferred.resolve(res.data)
     })
@@ -33,19 +33,6 @@
 
     return deferred.promise;
   }
-  this.getVpnTenants = (tenantId) => {
-    let deferred = $q.defer();
-
-    $http.get('/xoslib/clientscript/', {params: {tenantId: tenantId}})
-    .then((res) => {
-      deferred.resolve(res.data)
-    })
-    .catch((e) => {
-      deferred.reject(e);
-    });
-
-    return deferred.promise;
-  };
 })
 .config(function($httpProvider){
   $httpProvider.interceptors.push('NoHyperlinks');
@@ -66,27 +53,12 @@
       .catch((e) => {
         throw new Error(e);
       });
-    }
-  };
-})
-.directive('clientScript', function(){
-  return {
-    restrict: 'E',
-    scope: {
-      tenantId: '=tenantId',
-    },
-    bindToController: true,
-    controllerAs: 'vm',
-    templateUrl: 'templates/client-script.tpl.html',
-    controller: function(Vpn){
-      // retrieving user list
-      Vpn.getClientScript(tenantId)
-      .then((script_location) => {
-        this.script_location = script_location;
-      })
-      .catch((e) => {
-        throw new Error(e);
-      });
+
+      this.getScriptLocation = function(vpn) {
+        var content = vpn.create_client_script();
+        var blob = new Blob([ content ], { type : 'text/plain' });
+        return (window.URL || window.webkitURL).createObjectURL( blob );
+      }
     }
   };
 });
diff --git a/views/ngXosViews/vpnDashboard/src/templates/client-script.tpl.html b/views/ngXosViews/vpnDashboard/src/templates/client-script.tpl.html
deleted file mode 100644
index 6810580..0000000
--- a/views/ngXosViews/vpnDashboard/src/templates/client-script.tpl.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<a href="/static/vpn/{{ vm.script_location }}" download id="download" hidden>{{ vm.script_location }}</a>
-<script>
-// document.getElementById('download').click();
-</script>
diff --git a/views/ngXosViews/vpnDashboard/src/templates/vpn-list.tpl.html b/views/ngXosViews/vpnDashboard/src/templates/vpn-list.tpl.html
index 8d4df52..95d197f 100644
--- a/views/ngXosViews/vpnDashboard/src/templates/vpn-list.tpl.html
+++ b/views/ngXosViews/vpnDashboard/src/templates/vpn-list.tpl.html
@@ -1,17 +1,19 @@
-<div class="row">
-  <h1>VPN List</h1>
-</div>
-<div class="row">
-  <div class="cell">ID</div>
-  <div class="cell">VPN Network</div>
-  <div class="cell">VPN Subnet</div>
-  <div class="cell">Script Link</div>
-</div>
-<div class="row" ng-repeat="vpn in vm.vpns">
-  <div class="cell">{{vpn.instance.instance_id}}</div>
-  <div class="cell">{{vpn.server_network}}</div>
-  <div class="cell">{{vpn.vpn_subnet}}</div>
-  <div class="cell">
-    <a href="client/{{ vpn.pk }}/" target="_blank">Script</a>
+<div style="display: table;">
+  <div class="row">
+    <h1 class="cell">VPN List</h1>
+  </div>
+  <div class="row">
+    <div class="cell header">ID</div>
+    <div class="cell header">VPN Network</div>
+    <div class="cell header">VPN Subnet</div>
+    <div class="cell header">Script Link</div>
+  </div>
+  <div class="row" ng-repeat="vpn in vm.vpns">
+    <div class="cell">{{ vpn.id }}</div>
+    <div class="cell">{{ vpn.server_network }}</div>
+    <div class="cell">{{ vpn.vpn_subnet }}</div>
+    <div class="cell">
+      <a download="connect-{{ vpn.id }}.vpn" ng-href="{{ vm.getScriptLocation(vpn) }}">Script</a>
+    </div>
   </div>
 </div>
diff --git a/xos/core/xoslib/methods/vpnview.py b/xos/core/xoslib/methods/vpnview.py
index f8983ab..ccbb2e7 100644
--- a/xos/core/xoslib/methods/vpnview.py
+++ b/xos/core/xoslib/methods/vpnview.py
@@ -1,16 +1,65 @@
 from django.core.exceptions import PermissionDenied
+from plus import PlusSerializerMixin
+from rest_framework import serializers
 from rest_framework.response import Response
+from rest_framework.status import HTTP_200_OK
 from rest_framework.views import APIView
-from services.vpn.models import VPNTenant
+from services.vpn.models import VPNService, VPNTenant
+from xos.apibase import XOSListCreateAPIView
 
-class VpnTenantsList(APIView):
+if hasattr(serializers, "ReadOnlyField"):
+    # rest_framework 3.x
+    ReadOnlyField = serializers.ReadOnlyField
+else:
+    # rest_framework 2.x
+    ReadOnlyField = serializers.Field
+
+def get_default_vpn_service():
+    vpn_services = VPNService.get_service_objects().all()
+    if vpn_services:
+        return vpn_services[0].id
+    return None
+
+class VPNTenantSerializer(serializers.ModelSerializer, PlusSerializerMixin):
+        id = ReadOnlyField()
+        service_specific_attribute = ReadOnlyField()
+        server_network = ReadOnlyField()
+        vpn_subnet = ReadOnlyField()
+        is_persistent = ReadOnlyField()
+        clients_can_see_each_other = ReadOnlyField()
+        ca_crt = ReadOnlyField()
+        port_number = ReadOnlyField()
+        creator = ReadOnlyField()
+        instance = ReadOnlyField()
+        provider_service = serializers.PrimaryKeyRelatedField(queryset=VPNService.get_service_objects().all(), default=get_default_vpn_service)
+
+        humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+
+        computeNodeName = serializers.SerializerMethodField("getComputeNodeName")
+
+        class Meta:
+            model = VPNTenant
+            fields = ('humanReadableName', 'id', 'provider_service',
+                      'service_specific_attribute', 'vpn_subnet',
+                      'server_network', 'creator', 'instance',
+                      'computeNodeName', 'is_persistent', 'clients_can_see_each_other',
+                      'ca_crt', 'port_number')
+
+        def getHumanReadableName(self, obj):
+            return obj.__unicode__()
+
+        def getComputeNodeName(self, obj):
+            instance = obj.instance
+            if not instance:
+                return None
+            return instance.node.name
+
+class VPNTenantList(XOSListCreateAPIView):
+    serializer_class = VPNTenantSerializer
+    queryset = VPNTenant.get_tenant_objects().all()
     method_kind = "list"
-    method_name = "vpntenants"
+    method_name = "vpntenant"
 
-    def get(self, request, format=None):
-        if (not request.user.is_authenticated()):
-            raise PermissionDenied("You must be authenticated in order to use this API")
-        return Response(VPNTenant.get_tenant_objects())
 
 class ClientScript(APIView):
     method_kind = "detail"
@@ -19,5 +68,6 @@
     def get(self, request, format=None):
         if (not request.user.is_authenticated()):
             raise PermissionDenied("You must be authenticated in order to use this API")
-        teant_id = request.QUERY_PARAMS.get('tenantId', None)
-        return Response(VPNTenant.get_tenant_objects().filter(pk=tenantId))
+        tenantId = request.QUERY_PARAMS.get('tenantId', None)
+        serializer = VPNTenantSerializer(VPNTenant.get_tenant_objects().filter(id=tenantId)[0])
+        return Response(serializer.data, status=HTTP_200_OK)
diff --git a/xos/services/vpn/models.py b/xos/services/vpn/models.py
index 7e324af..146168f 100644
--- a/xos/services/vpn/models.py
+++ b/xos/services/vpn/models.py
@@ -32,7 +32,6 @@
                           'server_network': None,
                           'clients_can_see_each_other': True,
                           'is_persistent': True,
-                          'script': None,
                           'ca_crt': None,
                           'port': None}
 
@@ -140,36 +139,25 @@
     def port_number(self, value):
         self.set_attribute("port", value)
 
-    @property
-    def script(self):
-        """string: the location of the client script that is generated when
-           this method is called.
-        """
-        script_name = str(time.time()) + ".vpn"
-        self.create_client_script(script_name)
-        return script_name
-
-    def create_client_script(self, script_name):
-        script = open("/opt/xos/core/static/vpn/" + script_name, 'w')
+    def create_client_script(self):
+        script = ""
         # write the configuration portion
-        script.write("printf \"%b\" \"")
-        for line in self.generate_client_conf().splitlines():
-            script.write(line + r"\n")
-        script.write("\" > client.conf\n")
-        script.write("printf \"%b\" \"")
-        for line in self.generate_login().splitlines():
-            script.write(line + r"\n")
-        script.write("\" > login.up\n")
-        script.write("printf \"%b\" \"")
+        script += ("printf \"%b\" \"")
+        script += self.generate_client_conf()
+        script += ("\" > client.conf\n")
+        script += ("printf \"%b\" \"")
+        script += self.generate_login()
+        script += ("\" > login.up\n")
+        script += ("printf \"%b\" \"")
         for line in self.ca_crt:
-            script.write(line.rstrip() + r"\n")
-        script.write("\" > ca.crt\n")
+            script += (line.rstrip() + r"\n")
+        script += ("\" > ca.crt\n")
         # make sure openvpn is installed
-        script.write("apt-get update\n")
-        script.write("apt-get install openvpn\n")
-        script.write("openvpn client.conf &\n")
+        script += ("apt-get update\n")
+        script += ("apt-get install openvpn\n")
+        script += ("openvpn client.conf &\n")
         # close the script
-        script.close()
+        return script;
 
     def generate_login(self):
         return str(time.time()) + "\npassword\n"