Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/api/examples/util.sh b/xos/api/examples/util.sh
index b3d3060..648b32c 100644
--- a/xos/api/examples/util.sh
+++ b/xos/api/examples/util.sh
@@ -41,7 +41,7 @@
fi
ID=`echo $JSON | python -c "import json,sys; print json.load(sys.stdin)['related'].get('vsg_id','')"`
if [[ $ID == "" ]]; then
- echo "there is no volt for this subscriber" >&2
+ echo "there is no vsg for this subscriber" >&2
exit -1
fi
diff --git a/xos/api/import_methods.py b/xos/api/import_methods.py
index 1b5e3ca..3702f8a 100644
--- a/xos/api/import_methods.py
+++ b/xos/api/import_methods.py
@@ -30,7 +30,16 @@
def import_module_by_dotted_name(name):
print "import", name
- module = __import__(name)
+ try:
+ module = __import__(name)
+ except:
+ # django will eat the exception, and then fail later with
+ # 'conflicting models in application'
+ # when it tries to import the module a second time.
+ print "exception in import_model_by_dotted_name"
+ import traceback
+ traceback.print_exc()
+ raise
for part in name.split(".")[1:]:
module = getattr(module, part)
return module
diff --git a/xos/api/service/vtn.py b/xos/api/service/vtn.py
new file mode 100644
index 0000000..6b02616
--- /dev/null
+++ b/xos/api/service/vtn.py
@@ -0,0 +1,96 @@
+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 viewsets
+from rest_framework.decorators import detail_route, list_route
+from rest_framework.views import APIView
+from core.models import *
+from services.vtn.models import VTNService
+from django.forms import widgets
+from django.conf.urls import patterns, url
+from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
+from django.shortcuts import get_object_or_404
+from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
+from xos.exceptions import *
+import json
+import subprocess
+
+class VTNServiceSerializer(PlusModelSerializer):
+ id = ReadOnlyField()
+
+ privateGatewayMac = serializers.CharField(required=False)
+ localManagementIp = serializers.CharField(required=False)
+ ovsdbPort = serializers.IntegerField(required=False)
+ sshPort = serializers.IntegerField(required=False)
+ sshUser = serializers.CharField(required=False)
+ sshKeyFile = serializers.CharField(required=False)
+ mgmtSubnetBits = serializers.IntegerField(required=False)
+ xosEndpoint = serializers.CharField(required=False)
+ xosUser = serializers.CharField(required=False)
+ xosPassword = serializers.CharField(required=False)
+
+
+ humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+ class Meta:
+ model = VTNService
+ fields = ('humanReadableName', 'id', 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile',
+ 'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword')
+
+ def getHumanReadableName(self, obj):
+ return obj.__unicode__()
+
+class VTNViewSet(XOSViewSet):
+ base_name = "vtn"
+ method_name = "vtn"
+ method_kind = "viewset"
+
+ # these are just because ViewSet needs some queryset and model, even if we don't use the
+ # default endpoints
+ queryset = VTNService.get_service_objects().all()
+ model = VTNService
+ serializer_class = VTNServiceSerializer
+
+ @classmethod
+ def get_urlpatterns(self, api_path="^"):
+ patterns = []
+
+ patterns.append( self.detail_url("services/$", {"get": "get_services"}, "services") )
+ patterns.append( self.detail_url("services_names/$", {"get": "get_services_names"}, "services") )
+ patterns.append( self.detail_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "get_service") )
+
+ # Not as RESTful as it could be, but maintain these endpoints for compability
+ patterns.append( self.list_url("services/$", {"get": "get_services"}, "rootvtn_services") )
+ patterns.append( self.list_url("services_names/$", {"get": "get_services_names"}, "rootvtn_services") )
+ patterns.append( self.list_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "rootvtn_get_service") )
+
+ patterns = patterns + super(VTNViewSet,self).get_urlpatterns(api_path)
+
+ return patterns
+
+ def get_services_names(self, request, pk=None):
+ result = {}
+ for service in Service.objects.all():
+ for id in service.get_vtn_src_names():
+ dependencies = service.get_vtn_dependencies_names()
+ if dependencies:
+ result[id] = dependencies
+ return Response(result)
+
+ def get_services(self, request, pk=None):
+ result = {}
+ for service in Service.objects.all():
+ for id in service.get_vtn_src_ids():
+ dependencies = service.get_vtn_dependencies_ids()
+ if dependencies:
+ result[id] = dependencies
+ return Response(result)
+
+ def get_service(self, request, pk=None, service=None):
+ for xos_service in Service.objects.all():
+ if service in xos_service.get_vtn_src_ids():
+ return Response(xos_service.get_vtn_dependencies_ids())
+ return Response([])
+
+
diff --git a/xos/api/tenant/cord/vsg.py b/xos/api/tenant/cord/vsg.py
new file mode 100644
index 0000000..6807e98
--- /dev/null
+++ b/xos/api/tenant/cord/vsg.py
@@ -0,0 +1,62 @@
+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.cord.models import VSGTenant, VSGService, CordSubscriberRoot
+from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
+from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
+
+def get_default_vsg_service():
+ vsg_services = VSGService.get_service_objects().all()
+ if vsg_services:
+ return vsg_services[0].id
+ return None
+
+class VSGTenantForAPI(VSGTenant):
+ class Meta:
+ proxy = True
+ app_label = "cord"
+
+ @property
+ def related(self):
+ related = {}
+ if self.instance:
+ related["instance_id"] = self.instance.id
+ return related
+
+class VSGTenantSerializer(PlusModelSerializer):
+ id = ReadOnlyField()
+ wan_container_ip = serializers.CharField()
+ wan_container_mac = ReadOnlyField()
+ related = serializers.DictField(required=False)
+
+ humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+ class Meta:
+ model = VSGTenantForAPI
+ fields = ('humanReadableName', 'id', 'wan_container_ip', 'wan_container_mac', 'related' )
+
+ def getHumanReadableName(self, obj):
+ return obj.__unicode__()
+
+class VSGTenantViewSet(XOSViewSet):
+ base_name = "vsg"
+ method_name = "vsg"
+ method_kind = "viewset"
+ queryset = VSGTenantForAPI.get_tenant_objects().all()
+ serializer_class = VSGTenantSerializer
+
+ @classmethod
+ def get_urlpatterns(self, api_path="^"):
+ patterns = super(VSGTenantViewSet, self).get_urlpatterns(api_path=api_path)
+
+ return patterns
+
+
+
+
+
+
diff --git a/xos/api/utility/__init__.py b/xos/api/utility/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/xos/api/utility/__init__.py
@@ -0,0 +1 @@
+
diff --git a/xos/api/utility/loginview.py b/xos/api/utility/loginview.py
new file mode 100644
index 0000000..2dc79c6
--- /dev/null
+++ b/xos/api/utility/loginview.py
@@ -0,0 +1,101 @@
+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.views import APIView
+from core.models import *
+from services.hpc.models import *
+from services.requestrouter.models import *
+from django.forms import widgets
+from django.core.exceptions import PermissionDenied
+from django.contrib.contenttypes.models import ContentType
+import json
+import socket
+import time
+import django.middleware.csrf
+from xos.exceptions import *
+from django.contrib.sessions.backends.db import SessionStore
+from django.contrib.sessions.models import Session
+from django.contrib.auth import authenticate
+
+def date_handler(obj):
+ return obj.isoformat() if hasattr(obj, 'isoformat') else obj
+
+def serialize_user(model):
+ serialized = model_to_dict(model)
+ del serialized['timezone']
+ del serialized['password']
+ return json.dumps(serialized, default=date_handler)
+
+class LoginView(APIView):
+ method_kind = "list"
+ method_name = "login"
+
+ def do_login(self, request, username, password):
+ if not username:
+ raise XOSMissingField("No username specified")
+
+ if not password:
+ raise XOSMissingField("No password specified")
+
+ u=authenticate(username=username, password=password)
+ if not u:
+ raise PermissionDenied("Failed to authenticate user %s" % username)
+
+ auth = {"username": username, "password": password}
+ request.session["auth"] = auth
+ request.session['_auth_user_id'] = u.pk
+ request.session['_auth_user_backend'] = u.backend
+ request.session.save()
+
+ return Response({
+ "xoscsrftoken": django.middleware.csrf.get_token(request),
+ "xossessionid": request.session.session_key,
+ "user": serialize_user(u)
+ })
+
+ def get(self, request, format=None):
+ username = request.GET.get("username", None)
+ password = request.GET.get("password", None)
+
+ return self.do_login(request, username, password)
+
+ def post(self, request, format=None):
+ username = request.data.get("username", None)
+ password = request.data.get("password", None)
+
+ return self.do_login(request, username, password)
+
+class LogoutView(APIView):
+ method_kind = "list"
+ method_name = "logout"
+
+ def do_logout(self, request, sessionid):
+ if not sessionid:
+ raise XOSMissingField("No xossessionid specified")
+
+ # Make sure the session exists. This prevents us from accidentally
+ # creating empty sessions with SessionStore()
+ session = Session.objects.filter(session_key=sessionid)
+ if not session:
+ # session doesn't exist
+ raise PermissionDenied("Session does not exist")
+
+ session = SessionStore(session_key=sessionid)
+ if "auth" in session:
+ del session["auth"]
+ session.save()
+ if "_auth_user_id" in session:
+ del session["_auth_user_id"]
+ session.save()
+
+ return Response("Logged Out")
+
+ def get(self, request, format=None):
+ sessionid = request.GET.get("xossessionid", None)
+ return self.do_logout(request, sessionid)
+
+ def post(self, request, format=None):
+ sessionid = request.data.get("xossessionid", None)
+ return self.do_logout(request, sessionid)
\ No newline at end of file
diff --git a/xos/configurations/acord/Makefile b/xos/configurations/acord/Makefile
index b5b93fa..cfa04f8 100644
--- a/xos/configurations/acord/Makefile
+++ b/xos/configurations/acord/Makefile
@@ -8,8 +8,9 @@
cord:
sudo MYIP=$(MYIP) docker-compose up -d
bash ../common/wait_for_xos.sh
- sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
- sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+ sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+ sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
acord: cord
diff --git a/xos/configurations/common/cloudlab-openstack.yaml b/xos/configurations/common/cloudlab-openstack.yaml
new file mode 100644
index 0000000..969f84c
--- /dev/null
+++ b/xos/configurations/common/cloudlab-openstack.yaml
@@ -0,0 +1,89 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+# Note:
+# assumes mydeployment.yaml has already been run, and the following exist:
+# MyDeployment
+# mysite
+# padmin@vicci.org
+# Public Shared IPv4
+# assumes the following have been created and filled with appropriate data:
+# /root/setup/admin_openrc
+# /root/setup/flat_net_name
+# /root/setup/padmin_public_key
+
+description: >
+ * Adds OpenCloud Sites, Deployments, and Controllers.
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+ trusty-server-multi-nic:
+ type: tosca.nodes.Image
+ properties:
+ disk_format: QCOW2
+ container_format: BARE
+
+ MyDeployment:
+ type: tosca.nodes.Deployment
+ properties:
+ no-create: True
+ no-delete: True
+ requirements:
+ - image:
+ node: trusty-server-multi-nic
+ relationship: tosca.relationships.SupportsImage
+
+ CloudLab:
+ type: tosca.nodes.Controller
+ requirements:
+ - deployment:
+ node: MyDeployment
+ relationship: tosca.relationships.ControllerDeployment
+ properties:
+ backend_type: OpenStack
+ version: Kilo
+ auth_url: { get_script_env: [ SELF, adminrc, OS_AUTH_URL, LOCAL_FILE] }
+ admin_user: { get_script_env: [ SELF, adminrc, OS_USERNAME, LOCAL_FILE] }
+ admin_password: { get_script_env: [ SELF, adminrc, OS_PASSWORD, LOCAL_FILE] }
+ admin_tenant: { get_script_env: [ SELF, adminrc, OS_TENANT_NAME, LOCAL_FILE] }
+ rabbit_user: { get_script_env: [ SELF, controller_settings, RABBIT_USER, LOCAL_FILE] }
+ rabbit_password: { get_script_env: [ SELF, controller_settings, RABBIT_PASS, LOCAL_FILE] }
+ rabbit_host: { get_script_env: [ SELF, controller_settings, CONTROLLER_FLAT_LAN_IP, LOCAL_FILE] }
+ domain: Default
+ artifacts:
+ adminrc: /root/setup/admin-openrc.sh
+ controller_settings: /root/setup/controller_settings
+
+ mysite:
+ type: tosca.nodes.Site
+ properties:
+ no-create: True
+ no-delete: True
+ requirements:
+ - deployment:
+ node: MyDeployment
+ relationship: tosca.relationships.SiteDeployment
+ requirements:
+ - controller:
+ node: CloudLab
+ relationship: tosca.relationships.UsesController
+
+ Public shared IPv4:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ no-create: True
+ no-delete: True
+ shared_network_name: { get_artifact: [ SELF, flat_net_name, LOCAL_FILE] }
+ artifacts:
+ flat_net_name: /root/setup/flat_net_name
+
+ padmin@vicci.org:
+ type: tosca.nodes.User
+ properties:
+ no-create: True
+ no-delete: True
+ public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE ] }
+ artifacts:
+ pubkey: /root/setup/padmin_public_key
diff --git a/xos/configurations/common/fixtures.yaml b/xos/configurations/common/fixtures.yaml
index 6419211..6d9c0e8 100644
--- a/xos/configurations/common/fixtures.yaml
+++ b/xos/configurations/common/fixtures.yaml
@@ -7,6 +7,11 @@
topology_template:
node_templates:
+
+# -----------------------------------------------------------------------------
+# Network Parameter Types
+# -----------------------------------------------------------------------------
+
s_tag:
type: tosca.nodes.NetworkParameterType
@@ -24,3 +29,97 @@
neutron_port_name:
type: tosca.nodes.NetworkParameterType
+
+# ----------------------------------------------------------------------------
+# Roles
+# ----------------------------------------------------------------------------
+
+ siterole#admin:
+ type: tosca.nodes.SiteRole
+
+ siterole#pi:
+ type: tosca.nodes.SiteRole
+
+ siterole#tech:
+ type: tosca.nodes.SiteRole
+
+ tenantrole#admin:
+ type: tosca.nodes.TenantRole
+
+ tenantrole#access:
+ type: tosca.nodes.TenantRole
+
+ deploymentrole#admin:
+ type: tosca.nodes.DeploymentRole
+
+ slicerole#admin:
+ type: tosca.nodes.SliceRole
+
+ slicerole#access:
+ type: tosca.nodes.SliceRole
+
+# -----------------------------------------------------------------------------
+# Flavors
+# -----------------------------------------------------------------------------
+
+ m1.small:
+ type: tosca.nodes.Flavor
+
+ m1.medium:
+ type: tosca.nodes.Flavor
+
+ m1.large:
+ type: tosca.nodes.Flavor
+
+# -----------------------------------------------------------------------------
+# Dashboard Views
+# -----------------------------------------------------------------------------
+
+ xsh:
+ type: tosca.nodes.DashboardView
+ properties:
+ url: template:xsh
+
+ Customize:
+ type: tosca.nodes.DashboardView
+ properties:
+ url: template:customize
+
+ Tenant:
+ type: tosca.nodes.DashboardView
+ properties:
+ url: template:xosTenant
+
+ Developer:
+ type: tosca.nodes.DashboardView
+ properties:
+ url: template:xosDeveloper_datatables
+
+# -----------------------------------------------------------------------------
+# Network Templates
+# -----------------------------------------------------------------------------
+
+ Private:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ visibility: private
+ translation: none
+
+ Public shared IPv4:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ visibility: private
+ translation: NAT
+ shared_network_name: nat-net
+
+ Public dedicated IPv4:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ visibility: public
+ translation: none
+ shared_network_name: ext-net
+
+
+
+
+
diff --git a/xos/configurations/common/mydeployment.yaml b/xos/configurations/common/mydeployment.yaml
index 9d2c951..66bb75d 100644
--- a/xos/configurations/common/mydeployment.yaml
+++ b/xos/configurations/common/mydeployment.yaml
@@ -38,13 +38,16 @@
node: MyDeployment
relationship: tosca.relationships.SiteDeployment
- # Include the Tenant view so we can make it a default of padmin@vicci.org
+ # Attach the Tenant view to the MyDeployment deployment
Tenant:
type: tosca.nodes.DashboardView
properties:
no-create: true
- no-update: true
no-delete: true
+ requirements:
+ - deployment:
+ node: MyDeployment
+ relationship: tosca.relationships.SupportsDeployment
padmin@vicci.org:
type: tosca.nodes.User
@@ -62,3 +65,5 @@
node: Tenant
relationship: tosca.relationships.UsesDashboard
+
+
diff --git a/xos/configurations/cord-deprecated/Makefile b/xos/configurations/cord-deprecated/Makefile
index 1e53e79..184f2d5 100644
--- a/xos/configurations/cord-deprecated/Makefile
+++ b/xos/configurations/cord-deprecated/Makefile
@@ -8,8 +8,9 @@
cord: virtualbng_json vtn_network_cfg_json
sudo MYIP=$(MYIP) docker-compose up -d
bash ../common/wait_for_xos.sh
- sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
- sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+ sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+ sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord/cord.yaml
diff --git a/xos/configurations/cord-pod/Makefile b/xos/configurations/cord-pod/Makefile
index f1111b4..ce1baf8 100644
--- a/xos/configurations/cord-pod/Makefile
+++ b/xos/configurations/cord-pod/Makefile
@@ -2,17 +2,17 @@
xos: nodes.yaml images.yaml
sudo docker-compose up -d
../common/wait_for_xos_port.sh 80
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/setup.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/images.yaml
-vtn:
+vtn: vtn-external.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/vtn-external.yaml
-cord: virtualbng_json
+cord:
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/mgmt-net.yaml
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-vtn-vsg.yaml
exampleservice:
@@ -27,6 +27,9 @@
images.yaml:
export SETUPDIR=.; bash ../common/make-images-yaml.sh
+vtn-external.yaml:
+ export SETUPDIR=.; bash ./make-vtn-external-yaml.sh
+
virtualbng_json:
export SETUPDIR=.; bash ./make-virtualbng-json.sh
diff --git a/xos/configurations/cord-pod/README.md b/xos/configurations/cord-pod/README.md
index 871bd30..d5051c9 100644
--- a/xos/configurations/cord-pod/README.md
+++ b/xos/configurations/cord-pod/README.md
@@ -31,7 +31,7 @@
To set up OpenStack, follow the instructions in the
[README.md](https://github.com/open-cloud/openstack-cluster-setup/blob/master/README.md)
file of the [open-cloud/openstack-cluster-setup](https://github.com/open-cloud/openstack-cluster-setup/)
-repository. If you're just getting started with CORD, it's probably best to begin with the
+repository. If you're just getting started with CORD, it's probably best to begin with the
single-node CORD test environment to familiarize yourself with the overall setup.
**NOTE: In order to use the cord-pod configuration, you must set up OpenStack using the above recipe.**
@@ -73,15 +73,15 @@
ubuntu@xos:~$ cd xos/xos/configurations/cord-pod
```
-Next, check that the following files exist in this directory:
+Next, check that the following files exist in this directory
+(they will have been put there for you by the cluster installation scripts):
* *admin-openrc.sh*: Admin credentials for your OpenStack cloud
* *id_rsa[.pub]*: A keypair that will be used by the various services
* *node_key*: A private key that allows root login to the compute nodes
-They will have been put there for you by the cluster installation scripts.
-
-XOS can then be brought up for CORD by running a few `make` commands:
+XOS can then be brought up for CORD by running a few `make` commands.
+First, run:
```
ubuntu@xos:~/xos/xos/configurations/cord-pod$ make
@@ -93,37 +93,56 @@
being sync'ed with OpenStack. Log into the GUI and select *Users*
at left. Make sure there is a green check next to `padmin@vicci.org`.
-Next, you may need to edit `vtn-external.yml` so that `rest_hostname:`
-points to the host where ONOS should run the VTN app. Then run:
+> If you are **not** building the single-node development POD, the next
+> step is to create and edit the VTN configuration. Run `make vtn-external.yaml`
+> then edit the `vtn-external.yml` TOSCA file. The `rest_hostname:`
+> field points to the host where ONOS should run the VTN app. The
+> fields in the `service_vtn` and the objects of type `tosca.nodes.Tag`
+> correspond to the VTN fields listed
+> on [the CORD VTN page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN),
+> under the **ONOS Settings** heading; refer there for the fields'
+> meanings.
+
+Then run:
```
ubuntu@xos:~/xos/xos/configurations/cord-pod$ make vtn
```
The above step configures the ONOS VTN app by generating a configuration
-and pushing it to ONOS. **If you are not setting up the single-node development POD**, you will
-need to modify the generated configuration via the XOS GUI. (The defaults
-should be OK for the single-node POD.) For more information
-about how to configure VTN, see [this page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN),
-under the **ONOS Settings** heading.
+and pushing it to ONOS. You are able to see and modify the configuration
+via the GUI as follows:
-* To see the generated configuration, go to http://xos/admin/onos/onosapp/, select
+* To see the generated configuration, go to *http://xos/admin/onos/onosapp/*, select
*VTN_ONOS_app*, then the *Attributes* tab, and look for the
`rest_onos/v1/network/configuration/` attribute.
-* To change `privateGatewayMac`, `localManagementIp`, `ovsdbPort`, `sshPort`,
-`sshUser` or `sshKeyFile` in the generated configuration, select *Services* at
-left in the XOS GUI, then *service_vtn*. Modify these fields under *VTN Service Details*
-and then select *Save*.
-
-* To change `bridgeId`, `dataPlaneIntf`, or `dataPlaneIp` for a particular compute node, go to
-http://xos/admin/core/node/, select a node, then select the *Tags* tab. Modify the appropriate tag
-and then select *Save*.
+* To change the VTN configuration, modify the fields of the VTN Service object
+and the Tag objects associated with Nodes. Don't forget to select *Save*.
* After modifying the above fields, delete the `rest_onos/v1/network/configuration/` attribute
in the *ONOS_VTN_app* and select *Save*. The attribute will be regenerated using the new information.
-Finally modify `cord-vtn-vsg.yml` and change `addresses_vsg` so that it contains the IP address block,
-gateway IP, and gateway MAC of the fabric. (Again, the defaults are fine for the single-node POD.)
+* Alternatively, if you want to load your own VTN configuration manually, you can delete the
+`autogenerate` attribute from the *ONOS_VTN_app*, edit the configuration in the
+`rest_onos/v1/network/configuration/` attribute, and select *Save*.
+
+Before proceeding, check that the VTN app is controlling Open vSwitch on the compute nodes. Log
+into ONOS and run the `cordvtn-nodes` command:
+
+```
+$ ssh -p 8101 karaf@onos-cord # password is karaf
+onos> cordvtn-nodes
+hostname=nova-compute, hostMgmtIp=192.168.122.177/24, dpIp=192.168.199.1/24, br-int=of:0000000000000001, dpIntf=veth1, init=COMPLETE
+Total 1 nodes
+```
+The important part is the `init=COMPLETE` at the end. If you do not see this, refer to
+[the CORD VTN page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN) for
+help fixing the problem. This must be working to bring up VMs on the POD.
+
+> If you are **not** building the single-node development POD, modify `cord-vtn-vsg.yml`
+> and change `addresses_vsg` so that it contains the IP address block,
+> gateway IP, and gateway MAC of the CORD fabric.
+
Then run:
```
diff --git a/xos/configurations/cord-pod/make-vtn-external-yaml.sh b/xos/configurations/cord-pod/make-vtn-external-yaml.sh
new file mode 100644
index 0000000..c623394
--- /dev/null
+++ b/xos/configurations/cord-pod/make-vtn-external-yaml.sh
@@ -0,0 +1,107 @@
+FN=$SETUPDIR/vtn-external.yaml
+
+rm -f $FN
+
+cat >> $FN <<EOF
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+imports:
+ - custom_types/xos.yaml
+
+description: autogenerated node tags file for VTN configuration
+
+topology_template:
+ node_templates:
+
+ service_ONOS_CORD:
+ type: tosca.nodes.ONOSService
+ requirements:
+ properties:
+ kind: onos
+ view_url: /admin/onos/onosservice/$id$/
+ no_container: true
+ rest_hostname: onos-cord
+
+ service_vtn:
+ type: tosca.nodes.VTNService
+ properties:
+ view_url: /admin/vtn/vtnservice/$id$/
+ privateGatewayMac: 00:00:00:00:00:01
+ localManagementIp: 172.27.0.1/24
+ ovsdbPort: 6641
+ sshUser: root
+ sshKeyFile: /root/node_key
+ sshPort: 22
+ xosEndpoint: http://xos/
+ xosUser: padmin@vicci.org
+ xosPassword: letmein
+
+EOF
+
+NODES=$( bash -c "source $SETUPDIR/admin-openrc.sh ; nova host-list" |grep compute|awk '{print $2}' )
+I=0
+for NODE in $NODES; do
+ echo $NODE
+ cat >> $FN <<EOF
+ $NODE:
+ type: tosca.nodes.Node
+
+ # VTN bridgeId field for node $NODE
+ ${NODE}_bridgeId_tag:
+ type: tosca.nodes.Tag
+ properties:
+ name: bridgeId
+ value: of:0000000000000001
+ requirements:
+ - target:
+ node: $NODE
+ relationship: tosca.relationships.TagsObject
+ - service:
+ node: service_ONOS_CORD
+ relationship: tosca.relationships.MemberOfService
+
+ # VTN dataPlaneIntf field for node $NODE
+ ${NODE}_dataPlaneIntf_tag:
+ type: tosca.nodes.Tag
+ properties:
+ name: dataPlaneIntf
+ value: veth1
+ requirements:
+ - target:
+ node: $NODE
+ relationship: tosca.relationships.TagsObject
+ - service:
+ node: service_ONOS_CORD
+ relationship: tosca.relationships.MemberOfService
+
+ # VTN dataPlaneIp field for node $NODE
+ ${NODE}_dataPlaneIp_tag:
+ type: tosca.nodes.Tag
+ properties:
+ name: dataPlaneIp
+ value: 10.168.0.253/24
+ requirements:
+ - target:
+ node: $NODE
+ relationship: tosca.relationships.TagsObject
+ - service:
+ node: service_ONOS_CORD
+ relationship: tosca.relationships.MemberOfService
+
+EOF
+done
+
+cat >> $FN <<EOF
+ VTN_ONOS_app:
+ type: tosca.nodes.ONOSVTNApp
+ requirements:
+ - onos_tenant:
+ node: service_ONOS_CORD
+ relationship: tosca.relationships.TenantOfService
+ - vtn_service:
+ node: service_vtn
+ relationship: tosca.relationships.UsedByService
+ properties:
+ dependencies: org.onosproject.drivers, org.onosproject.drivers.ovsdb, org.onosproject.openflow-base, org.onosproject.ovsdb-base, org.onosproject.dhcp, org.onosproject.cordvtn, org.onosproject.olt, org.onosproject.igmp, org.onosproject.cordmcast
+ autogenerate: vtn-network-cfg
+EOF
\ No newline at end of file
diff --git a/xos/configurations/cord-pod/vtn-external.yaml b/xos/configurations/cord-pod/vtn-external.yaml
deleted file mode 100644
index 51cca08..0000000
--- a/xos/configurations/cord-pod/vtn-external.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_0
-
-description: Set up ONOS VTN app
-
-imports:
- - custom_types/xos.yaml
-
-topology_template:
- node_templates:
-
- service_ONOS_CORD:
- type: tosca.nodes.ONOSService
- requirements:
- properties:
- kind: onos
- view_url: /admin/onos/onosservice/$id$/
- no_container: true
- rest_hostname: onos-cord
-
- VTN_ONOS_app:
- type: tosca.nodes.ONOSVTNApp
- requirements:
- - onos_tenant:
- node: service_ONOS_CORD
- relationship: tosca.relationships.TenantOfService
- - vtn_service:
- node: service_vtn
- relationship: tosca.relationships.UsedByService
- properties:
- dependencies: org.onosproject.drivers, org.onosproject.drivers.ovsdb, org.onosproject.openflow-base, org.onosproject.ovsdb-base, org.onosproject.dhcp, org.onosproject.cordvtn, org.onosproject.olt, org.onosproject.igmp, org.onosproject.cordmcast
- autogenerate: vtn-network-cfg
-
- service_vtn:
- type: tosca.nodes.VTNService
- properties:
- view_url: /admin/vtn/vtnservice/$id$/
diff --git a/xos/configurations/devel/Makefile b/xos/configurations/devel/Makefile
index 1e650f3..e55f38b 100644
--- a/xos/configurations/devel/Makefile
+++ b/xos/configurations/devel/Makefile
@@ -7,7 +7,9 @@
xos:
sudo MYIP=$(MYIP) docker-compose up -d
bash ../common/wait_for_xos.sh
- sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+ sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
containers:
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index 27b0044..09c714b 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -4,6 +4,7 @@
sudo make -f ../common/Makefile.prereqs
sudo docker-compose up -d
bash ../common/wait_for_xos.sh
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
@@ -29,7 +30,6 @@
sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
mock-cord:
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/mocks/cord.yaml
sudo docker exec frontend_xos_1 cp /opt/xos/configurations/cord/xos_cord_config /opt/xos/xos_configuration/
sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
diff --git a/xos/configurations/opencloud/Makefile b/xos/configurations/opencloud/Makefile
index aef4946..03168ed 100644
--- a/xos/configurations/opencloud/Makefile
+++ b/xos/configurations/opencloud/Makefile
@@ -1,6 +1,7 @@
xos:
sudo docker-compose up -d
bash ./wait_for_xos.sh
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/opencloud/opencloud.yaml
containers:
diff --git a/xos/configurations/openvpn/Makefile b/xos/configurations/openvpn/Makefile
index f71f638..aa6f2d5 100644
--- a/xos/configurations/openvpn/Makefile
+++ b/xos/configurations/openvpn/Makefile
@@ -5,7 +5,9 @@
xos:
sudo MYIP=$(MYIP) docker-compose up -d
bash ../common/wait_for_xos.sh
- sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+ sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
frontend:
diff --git a/xos/configurations/syndicate/Makefile b/xos/configurations/syndicate/Makefile
index eb8050e..3b29ee5 100644
--- a/xos/configurations/syndicate/Makefile
+++ b/xos/configurations/syndicate/Makefile
@@ -7,7 +7,9 @@
xos: syndicate_config
sudo MYIP=$(MYIP) docker-compose up -d
bash ../common/wait_for_xos.sh
- sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+ sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
containers:
diff --git a/xos/configurations/test-standalone/Makefile b/xos/configurations/test-standalone/Makefile
index 4956607..3ef5848 100644
--- a/xos/configurations/test-standalone/Makefile
+++ b/xos/configurations/test-standalone/Makefile
@@ -29,10 +29,9 @@
sudo docker exec teststandalone_xos_db_1 psql -U postgres -d xos -c "SELECT truncate_tables('postgres');"
sudo docker exec teststandalone_xos_db_1 psql -U postgres -d xos -c "SELECT setval('core_tenant_id_seq', 1)"
sudo docker-compose run xos python /opt/xos/manage.py --noobserver --nomodelpolicy loaddata /opt/xos/core/fixtures/core_initial_data.json
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
-
test: restore-initial-db-status
diff --git a/xos/configurations/test/Makefile b/xos/configurations/test/Makefile
index adf349a..d4e54fd 100644
--- a/xos/configurations/test/Makefile
+++ b/xos/configurations/test/Makefile
@@ -7,7 +7,9 @@
xos:
sudo MYIP=$(MYIP) docker-compose up -d
bash ../common/wait_for_xos.sh
- sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+ sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+ sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
sudo MYIP=$(MYIP) docker-compose run xos bash -c "cd /opt/xos/tosca/tests; python ./alltests.py"
sudo MYIP=$(MYIP) docker-compose run xos bash -c "cd /opt/xos/tosca/tests; python ./allObserverTests.py"
diff --git a/xos/core/fixtures/core_initial_data.json b/xos/core/fixtures/core_initial_data.json
index db5bd10..01ff999 100644
--- a/xos/core/fixtures/core_initial_data.json
+++ b/xos/core/fixtures/core_initial_data.json
@@ -1,159 +1,6 @@
[
{
"fields": {
- "updated": "2015-02-17T22:06:38.620Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.620Z",
- "deleted": false,
- "backend_register": "{}",
- "role": "admin",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.siterole",
- "pk": 1
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.670Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.669Z",
- "deleted": false,
- "backend_register": "{}",
- "role": "pi",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.siterole",
- "pk": 2
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.731Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.730Z",
- "deleted": false,
- "backend_register": "{}",
- "role": "tech",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.siterole",
- "pk": 3
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.620Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.620Z",
- "deleted": false,
- "backend_register": "{}",
- "role": "admin",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.tenantrole",
- "pk": 1
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.620Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.620Z",
- "deleted": false,
- "backend_register": "{}",
- "role": "access",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.tenantrole",
- "pk": 2
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.894Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.894Z",
- "deleted": false,
- "backend_register": "{}",
- "role": "admin",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.deploymentrole",
- "pk": 1
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.953Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.953Z",
- "deleted": false,
- "deployments": [],
- "enabled": true,
- "name": "xsh",
- "backend_register": "{}",
- "url": "template:xsh",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.dashboardview",
- "pk": 1
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:39.011Z",
- "policed": null,
- "created": "2015-02-17T22:06:39.011Z",
- "deleted": false,
- "deployments": [],
- "enabled": true,
- "name": "Customize",
- "backend_register": "{}",
- "url": "template:customize",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.dashboardview",
- "pk": 2
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:39.244Z",
- "policed": null,
- "created": "2015-02-17T22:06:39.069Z",
- "deleted": false,
- "deployments": [
- ],
- "enabled": true,
- "name": "Tenant",
- "backend_register": "{}",
- "url": "template:xosTenant",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.dashboardview",
- "pk": 3
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:39.302Z",
- "policed": null,
- "created": "2015-02-17T22:06:39.302Z",
- "deleted": false,
- "deployments": [],
- "enabled": true,
- "name": "Developer",
- "backend_register": "{}",
- "url": "template:xosDeveloper_datatables",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.dashboardview",
- "pk": 4
-},
-{
- "fields": {
"updated": "2015-02-17T22:06:39.361Z",
"membershipFee": 0,
"policed": null,
@@ -171,159 +18,5 @@
},
"model": "core.serviceclass",
"pk": 1
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.236Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.095Z",
- "deleted": false,
- "deployments": [
- ],
- "description": null,
- "name": "m1.small",
- "backend_register": "{}",
- "default": false,
- "flavor": "m1.small",
- "backend_status": "0 - Provisioning in progress",
- "order": 0,
- "enacted": null
- },
- "model": "core.flavor",
- "pk": 1
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.394Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.287Z",
- "deleted": false,
- "deployments": [
- ],
- "description": null,
- "name": "m1.medium",
- "backend_register": "{}",
- "default": false,
- "flavor": "m1.medium",
- "backend_status": "0 - Provisioning in progress",
- "order": 0,
- "enacted": null
- },
- "model": "core.flavor",
- "pk": 2
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.561Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.445Z",
- "deleted": false,
- "deployments": [
- ],
- "description": null,
- "name": "m1.large",
- "backend_register": "{}",
- "default": false,
- "flavor": "m1.large",
- "backend_status": "0 - Provisioning in progress",
- "order": 0,
- "enacted": null
- },
- "model": "core.flavor",
- "pk": 3
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.778Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.778Z",
- "deleted": false,
- "backend_register": "{}",
- "role": "admin",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.slicerole",
- "pk": 1
-},
-{
- "fields": {
- "updated": "2015-02-17T22:06:38.836Z",
- "policed": null,
- "created": "2015-02-17T22:06:38.836Z",
- "deleted": false,
- "backend_register": "{}",
- "role": "access",
- "backend_status": "0 - Provisioning in progress",
- "enacted": null
- },
- "model": "core.slicerole",
- "pk": 2
-},
-{
- "fields": {
- "shared_network_id": null,
- "updated": "2015-02-17T22:06:39.419Z",
- "policed": null,
- "created": "2015-02-17T22:06:39.419Z",
- "deleted": false,
- "description": "A private virtual network",
- "visibility": "private",
- "name": "Private",
- "backend_register": "{}",
- "topology_kind": "bigswitch",
- "guaranteed_bandwidth": 0,
- "translation": "none",
- "backend_status": "0 - Provisioning in progress",
- "shared_network_name": null,
- "controller_kind": null,
- "enacted": null
- },
- "model": "core.networktemplate",
- "pk": 1
-},
-{
- "fields": {
- "shared_network_id": null,
- "updated": "2015-02-17T22:06:39.477Z",
- "policed": null,
- "created": "2015-02-17T22:06:39.477Z",
- "deleted": false,
- "description": "Connect a instance to the public network",
- "visibility": "private",
- "name": "Public shared IPv4",
- "backend_register": "{}",
- "topology_kind": "bigswitch",
- "guaranteed_bandwidth": 0,
- "translation": "NAT",
- "backend_status": "0 - Provisioning in progress",
- "shared_network_name": "nat-net",
- "controller_kind": null,
- "enacted": null
- },
- "model": "core.networktemplate",
- "pk": 2
-},
-{
- "fields": {
- "shared_network_id": null,
- "updated": "2015-02-17T22:06:39.536Z",
- "policed": null,
- "created": "2015-02-17T22:06:39.536Z",
- "deleted": false,
- "description": "Connect a instance to the public network",
- "visibility": "public",
- "name": "Public dedicated IPv4",
- "backend_register": "{}",
- "topology_kind": "bigswitch",
- "guaranteed_bandwidth": 0,
- "translation": "none",
- "backend_status": "0 - Provisioning in progress",
- "shared_network_name": "ext-net",
- "controller_kind": null,
- "enacted": null
- },
- "model": "core.networktemplate",
- "pk": 3
}
]
diff --git a/xos/core/models/plcorebase.py b/xos/core/models/plcorebase.py
index c8c25a7..060570d 100644
--- a/xos/core/models/plcorebase.py
+++ b/xos/core/models/plcorebase.py
@@ -2,6 +2,7 @@
import json
import os
import sys
+import threading
from django import db
from django.db import models
from django.forms.models import model_to_dict
@@ -198,7 +199,7 @@
# default values for created and updated are only there to keep evolution
# from failing.
created = models.DateTimeField(auto_now_add=True, default=timezone.now)
- updated = models.DateTimeField(auto_now=True, default=timezone.now)
+ updated = models.DateTimeField(default=timezone.now)
enacted = models.DateTimeField(null=True, blank=True, default=None)
policed = models.DateTimeField(null=True, blank=True, default=None)
@@ -270,6 +271,9 @@
if not (field in ["backend_register", "backend_status", "deleted", "enacted", "updated"]):
ignore_composite_key_check=False
+ if 'synchronizer' not in threading.current_thread().name:
+ self.updated = datetime.datetime.now()
+
super(PlCoreBase, self).save(*args, **kwargs)
# This is a no-op if observer_disabled is set
diff --git a/xos/core/xoslib/methods/loginview.py b/xos/core/xoslib/methods/loginview.py
old mode 100755
new mode 100644
index 69ee289..2dc79c6
--- a/xos/core/xoslib/methods/loginview.py
+++ b/xos/core/xoslib/methods/loginview.py
@@ -62,8 +62,8 @@
return self.do_login(request, username, password)
def post(self, request, format=None):
- username = request.DATA.get("username", None)
- password = request.DATA.get("password", None)
+ username = request.data.get("username", None)
+ password = request.data.get("password", None)
return self.do_login(request, username, password)
@@ -97,5 +97,5 @@
return self.do_logout(request, sessionid)
def post(self, request, format=None):
- sessionid = request.DATA.get("xossessionid", None)
+ sessionid = request.data.get("xossessionid", None)
return self.do_logout(request, sessionid)
\ No newline at end of file
diff --git a/xos/core/xoslib/methods/vtn.py b/xos/core/xoslib/methods/vtn.py
index 1a2af53..c9dbf3a 100644
--- a/xos/core/xoslib/methods/vtn.py
+++ b/xos/core/xoslib/methods/vtn.py
@@ -57,7 +57,8 @@
for xos_service in Service.objects.all():
if service in xos_service.get_vtn_src_ids():
return Response(xos_service.get_vtn_dependencies_ids())
- raise DoesNotExist()
+ return Response([])
+ # raise DoesNotExist()
def list(self, request):
raise Exception("Not Implemented")
diff --git a/xos/services/vtn/admin.py b/xos/services/vtn/admin.py
index c64e054..03ff5cd 100644
--- a/xos/services/vtn/admin.py
+++ b/xos/services/vtn/admin.py
@@ -29,6 +29,9 @@
sshUser = forms.CharField(required=False)
sshKeyFile = forms.CharField(required=False)
mgmtSubnetBits = forms.CharField(required=False)
+ xosEndpoint = forms.CharField(required=False)
+ xosUser = forms.CharField(required=False)
+ xosPassword = forms.CharField(required=False)
def __init__(self,*args,**kwargs):
super (VTNServiceForm,self ).__init__(*args,**kwargs)
@@ -40,6 +43,9 @@
self.fields['sshUser'].initial = self.instance.sshUser
self.fields['sshKeyFile'].initial = self.instance.sshKeyFile
self.fields['mgmtSubnetBits'].initial = self.instance.mgmtSubnetBits
+ self.fields['xosEndpoint'].initial = self.instance.xosEndpoint
+ self.fields['xosUser'].initial = self.instance.xosUser
+ self.fields['xosPassword'].initial = self.instance.xosPassword
def save(self, commit=True):
self.instance.privateGatewayMac = self.cleaned_data.get("privateGatewayMac")
@@ -49,6 +55,9 @@
self.instance.sshUser = self.cleaned_data.get("sshUser")
self.instance.sshKeyFile = self.cleaned_data.get("sshKeyFile")
self.instance.mgmtSubnetBits = self.cleaned_data.get("mgmtSubnetBits")
+ self.instance.xosEndpoint = self.cleaned_data.get("xosEndpoint")
+ self.instance.xosUser = self.cleaned_data.get("xosUser")
+ self.instance.xosPassword = self.cleaned_data.get("xosPassword")
return super(VTNServiceForm, self).save(commit=commit)
class Meta:
@@ -62,7 +71,7 @@
list_display = ("backend_status_icon", "name", "enabled")
list_display_links = ('backend_status_icon', 'name', )
fieldsets = [(None, {'fields': ['backend_status_text', 'name','enabled','versionNumber','description',"view_url","icon_url",
- 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits' ], 'classes':['suit-tab suit-tab-general']})]
+ 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword' ], 'classes':['suit-tab suit-tab-general']})]
readonly_fields = ('backend_status_text', )
inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
@@ -84,4 +93,3 @@
return VTNService.get_service_objects_by_user(request.user)
admin.site.register(VTNService, VTNServiceAdmin)
-
diff --git a/xos/services/vtn/models.py b/xos/services/vtn/models.py
index cb254d7..52b1633 100644
--- a/xos/services/vtn/models.py
+++ b/xos/services/vtn/models.py
@@ -37,8 +37,10 @@
("sshUser", "root"),
("sshKeyFile", "/root/node_key") ,
("mgmtSubnetBits", "24"),
+ ("xosEndpoint", "http://xos/"),
+ ("xosUser", "padmin@vicci.org"),
+ ("xosPassword", "letmein"),
)
VTNService.setup_simple_attributes()
-
diff --git a/xos/synchronizers/base/backend.py b/xos/synchronizers/base/backend.py
index 5f11d46..d7307fa 100644
--- a/xos/synchronizers/base/backend.py
+++ b/xos/synchronizers/base/backend.py
@@ -15,7 +15,7 @@
def run(self):
# start the openstack observer
observer = XOSObserver()
- observer_thread = threading.Thread(target=observer.run)
+ observer_thread = threading.Thread(target=observer.run,name='synchronizer')
observer_thread.start()
# start model policies thread
diff --git a/xos/synchronizers/base/event_loop.py b/xos/synchronizers/base/event_loop.py
index f224380..4f7d436 100644
--- a/xos/synchronizers/base/event_loop.py
+++ b/xos/synchronizers/base/event_loop.py
@@ -521,7 +521,12 @@
loop_end = time.time()
- diag = Diag.objects.filter(name=Config().observer_name).first()
+ try:
+ observer_name = Config().observer_name
+ except:
+ observer_name = ''
+
+ diag = Diag.objects.filter(name=observer_name).first()
if (diag):
br_str = diag.backend_register
br = json.loads(br_str)
diff --git a/xos/synchronizers/onos/steps/sync_onosapp.py b/xos/synchronizers/onos/steps/sync_onosapp.py
index 1233ad7..7b80641 100644
--- a/xos/synchronizers/onos/steps/sync_onosapp.py
+++ b/xos/synchronizers/onos/steps/sync_onosapp.py
@@ -118,18 +118,9 @@
raise Exception("Controller user object for %s does not exist" % instance.creator)
return cuser.kuser_id
-
- def node_tag_default(self, o, node, tagname, default):
+ def get_node_tag(self, o, node, tagname):
tags = Tag.select_by_content_object(node).filter(name=tagname)
- if tags:
- value = tags[0].value
- else:
- value = default
- logger.info("node %s: saving default value %s for tag %s" % (node.name, value, tagname))
- service = self.get_onos_service(o)
- tag = Tag(service=service, content_object=node, name=tagname, value=value)
- tag.save()
- return value
+ return tags[0].value
# Scan attrs for attribute name
# If it's not present, save it as a TenantAttribute
@@ -153,6 +144,9 @@
sshUser = None
sshKeyFile = None
mgmtSubnetBits = None
+ xosEndpoint = None
+ xosUser = None
+ xosPassword = None
# VTN-specific configuration from the VTN Service
vtns = VTNService.get_service_objects().all()
@@ -165,6 +159,9 @@
sshUser = vtn.sshUser
sshKeyFile = vtn.sshKeyFile
mgmtSubnetBits = vtn.mgmtSubnetBits
+ xosEndpoint = vtn.xosEndpoint
+ xosUser = vtn.xosUser
+ xosPassword = vtn.xosPassword
# OpenStack endpoints and credentials
keystone_server = "http://keystone:5000/v2.0/"
@@ -196,6 +193,11 @@
"user": user_name,
"password": password
},
+ "xos": {
+ "endpoint": xosEndpoint,
+ "user": xosUser,
+ "password": xosPassword
+ },
"publicGateways": [],
"nodes" : []
}
@@ -209,10 +211,9 @@
nodeip = socket.gethostbyname(node.name)
try:
- bridgeId = self.node_tag_default(o, node, "bridgeId", "of:0000000000000001")
- dataPlaneIntf = self.node_tag_default(o, node, "dataPlaneIntf", "veth1")
- # This should be generated from the AddressPool if not present
- dataPlaneIp = self.node_tag_default(o, node, "dataPlaneIp", "192.168.199.1/24")
+ bridgeId = self.get_node_tag(o, node, "bridgeId")
+ dataPlaneIntf = self.get_node_tag(o, node, "dataPlaneIntf")
+ dataPlaneIp = self.get_node_tag(o, node, "dataPlaneIp")
except:
logger.error("not adding node %s to the VTN configuration" % node.name)
continue
diff --git a/xos/synchronizers/vtr/steps/sync_vtrtenant.py b/xos/synchronizers/vtr/steps/sync_vtrtenant.py
index 8debadf..c66f19c 100644
--- a/xos/synchronizers/vtr/steps/sync_vtrtenant.py
+++ b/xos/synchronizers/vtr/steps/sync_vtrtenant.py
@@ -95,9 +95,9 @@
# add in the sync_attributes that come from the vSG object
# this will be wan_ip, wan_mac, wan_container_ip, wan_container_mac, ...
- if o.target and o.target.volt and o.target.volt.vsg:
- for attribute_name in o.target.volt.vsg.sync_attributes:
- fields[attribute_name] = getattr(o.target.volt.vsg, attribute_name)
+ if o.target and o.target.volt and o.target.volt.vcpe:
+ for attribute_name in o.target.volt.vcpe.sync_attributes:
+ fields[attribute_name] = getattr(o.target.volt.vcpe, attribute_name)
# add in the sync_attributes that come from the SubscriberRoot object
if o.target and hasattr(o.target, "sync_attributes"):
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index c114652..32eefa4 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -282,6 +282,16 @@
mgmtSubnetBits:
type: string
required: false
+ xosEndpoint:
+ type: string
+ required: false
+ xosUser:
+ type: string
+ required: false
+ xosPassword:
+ type: string
+ required: false
+
tosca.nodes.CDNService:
derived_from: tosca.nodes.Root
@@ -385,16 +395,17 @@
type: tosca.capabilities.xos.User
properties:
+ xos_base_props
password:
type: string
required: false
firstname:
type: string
- required: true
+ required: false
description: First name of User.
lastname:
type: string
- required: true
+ required: false
description: Last name of User.
phone:
type: string
@@ -410,11 +421,13 @@
description: Public key that will be installed in Instances.
is_active:
type: boolean
- default: true
+ required: false
+ #default: true
description: If True, the user may log in.
is_admin:
type: boolean
- default: false
+ required: false
+ #default: false
description: If True, the user has root admin privileges.
login_page:
type: string
@@ -428,6 +441,9 @@
An XOS network parameter type. May be applied to Networks and/or
Ports.
+ properties:
+ xos_base_props
+
capabilities:
network_parameter_type:
type: tosca.capabilities.xos.NetworkParameterType
@@ -444,13 +460,14 @@
type: tosca.capabilities.xos.NetworkTemplate
properties:
+ xos_base_props
visibility:
type: string
- default: private
+ required: false
description: Indicates whether network is publicly routable.
translation:
type: string
- default: none
+ required: false
description: Indicates whether network uses address translation.
shared_network_name:
type: string
@@ -462,7 +479,7 @@
description: Attaches this template to a specific OpenStack network.
topology_kind:
type: string
- default: BigSwitch
+ required: false
description: Describes the topology of the network.
controller_kind:
type: string
@@ -792,6 +809,46 @@
flavor:
type: tosca.capabilities.xos.Flavor
+ tosca.nodes.SiteRole:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Site Role.
+ properties:
+ xos_base_props
+ capabilities:
+ siterole:
+ type: tosca.capabilities.xos.SiteRole
+
+ tosca.nodes.SliceRole:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Slice Role.
+ properties:
+ xos_base_props
+ capabilities:
+ slicerole:
+ type: tosca.capabilities.xos.SliceRole
+
+ tosca.nodes.TenantRole:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Tenant Role.
+ properties:
+ xos_base_props
+ capabilities:
+ tenantrole:
+ type: tosca.capabilities.xos.TenantRole
+
+ tosca.nodes.DeploymentRole:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Deployment Role.
+ properties:
+ xos_base_props
+ capabilities:
+ deploymentrole:
+ type: tosca.capabilities.xos.DeploymentRole
+
tosca.nodes.DashboardView:
derived_from: tosca.nodes.Root
description: >
@@ -809,6 +866,21 @@
required: false
description: URL to the dashboard
+ tosca.nodes.Tag:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Tag
+ properties:
+ xos_base_props
+ name:
+ type: string
+ required: true
+ descrption: name of tag
+ value:
+ type: string
+ required: false
+ descrption: value of tag
+
tosca.nodes.Compute.Container:
derived_from: tosca.nodes.Compute
description: >
@@ -945,6 +1017,9 @@
tosca.relationships.DependsOn:
derived_from: tosca.relationships.Root
+ tosca.relationships.TagsObject:
+ derived_from: tosca.relationships.Root
+
tosca.capabilities.xos.Service:
derived_from: tosca.capabilities.Root
description: An XOS Service
@@ -997,6 +1072,22 @@
derived_from: tosca.capabilities.Root
description: An XOS Flavor
+ tosca.capabilities.xos.DeploymentRole:
+ derived_from: tosca.capabilities.Root
+ description: An XOS DeploymentRole
+
+ tosca.capabilities.xos.SliceRole:
+ derived_from: tosca.capabilities.Root
+ description: An XOS SliceRole
+
+ tosca.capabilities.xos.SiteRole:
+ derived_from: tosca.capabilities.Root
+ description: An XOS SiteRole
+
+ tosca.capabilities.xos.TenantRole:
+ derived_from: tosca.capabilities.Root
+ description: An XOS TenantRole
+
tosca.capabilities.xos.Image:
derived_from: tosca.capabilities.Root
description: An XOS Image
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index a89641c..8102d1c 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -516,6 +516,15 @@
mgmtSubnetBits:
type: string
required: false
+ xosEndpoint:
+ type: string
+ required: false
+ xosUser:
+ type: string
+ required: false
+ xosPassword:
+ type: string
+ required: false
tosca.nodes.CDNService:
derived_from: tosca.nodes.Root
@@ -730,16 +739,28 @@
type: tosca.capabilities.xos.User
properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
password:
type: string
required: false
firstname:
type: string
- required: true
+ required: false
description: First name of User.
lastname:
type: string
- required: true
+ required: false
description: Last name of User.
phone:
type: string
@@ -755,11 +776,13 @@
description: Public key that will be installed in Instances.
is_active:
type: boolean
- default: true
+ required: false
+ #default: true
description: If True, the user may log in.
is_admin:
type: boolean
- default: false
+ required: false
+ #default: false
description: If True, the user has root admin privileges.
login_page:
type: string
@@ -773,6 +796,20 @@
An XOS network parameter type. May be applied to Networks and/or
Ports.
+ properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
+
capabilities:
network_parameter_type:
type: tosca.capabilities.xos.NetworkParameterType
@@ -789,13 +826,25 @@
type: tosca.capabilities.xos.NetworkTemplate
properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
visibility:
type: string
- default: private
+ required: false
description: Indicates whether network is publicly routable.
translation:
type: string
- default: none
+ required: false
description: Indicates whether network uses address translation.
shared_network_name:
type: string
@@ -807,7 +856,7 @@
description: Attaches this template to a specific OpenStack network.
topology_kind:
type: string
- default: BigSwitch
+ required: false
description: Describes the topology of the network.
controller_kind:
type: string
@@ -1236,6 +1285,90 @@
flavor:
type: tosca.capabilities.xos.Flavor
+ tosca.nodes.SiteRole:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Site Role.
+ properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
+ capabilities:
+ siterole:
+ type: tosca.capabilities.xos.SiteRole
+
+ tosca.nodes.SliceRole:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Slice Role.
+ properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
+ capabilities:
+ slicerole:
+ type: tosca.capabilities.xos.SliceRole
+
+ tosca.nodes.TenantRole:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Tenant Role.
+ properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
+ capabilities:
+ tenantrole:
+ type: tosca.capabilities.xos.TenantRole
+
+ tosca.nodes.DeploymentRole:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Deployment Role.
+ properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
+ capabilities:
+ deploymentrole:
+ type: tosca.capabilities.xos.DeploymentRole
+
tosca.nodes.DashboardView:
derived_from: tosca.nodes.Root
description: >
@@ -1264,6 +1397,32 @@
required: false
description: URL to the dashboard
+ tosca.nodes.Tag:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Tag
+ properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
+ name:
+ type: string
+ required: true
+ descrption: name of tag
+ value:
+ type: string
+ required: false
+ descrption: value of tag
+
tosca.nodes.Compute.Container:
derived_from: tosca.nodes.Compute
description: >
@@ -1400,6 +1559,9 @@
tosca.relationships.DependsOn:
derived_from: tosca.relationships.Root
+ tosca.relationships.TagsObject:
+ derived_from: tosca.relationships.Root
+
tosca.capabilities.xos.Service:
derived_from: tosca.capabilities.Root
description: An XOS Service
@@ -1452,6 +1614,22 @@
derived_from: tosca.capabilities.Root
description: An XOS Flavor
+ tosca.capabilities.xos.DeploymentRole:
+ derived_from: tosca.capabilities.Root
+ description: An XOS DeploymentRole
+
+ tosca.capabilities.xos.SliceRole:
+ derived_from: tosca.capabilities.Root
+ description: An XOS SliceRole
+
+ tosca.capabilities.xos.SiteRole:
+ derived_from: tosca.capabilities.Root
+ description: An XOS SiteRole
+
+ tosca.capabilities.xos.TenantRole:
+ derived_from: tosca.capabilities.Root
+ description: An XOS TenantRole
+
tosca.capabilities.xos.Image:
derived_from: tosca.capabilities.Root
description: An XOS Image
diff --git a/xos/tosca/resources/CORDUser.py b/xos/tosca/resources/CORDUser.py
index 566e205..705a895 100644
--- a/xos/tosca/resources/CORDUser.py
+++ b/xos/tosca/resources/CORDUser.py
@@ -28,12 +28,12 @@
if not sub:
return []
for user in sub.users:
- if user["name"] == self.nodetemplate.name:
+ if user["name"] == self.obj_name:
result.append(user)
return result
def get_xos_args(self):
- args = {"name": self.nodetemplate.name,
+ args = {"name": self.obj_name,
"level": self.get_property("level"),
"mac": self.get_property("mac")}
return args
@@ -46,7 +46,7 @@
sub.create_user(**xos_args)
sub.save()
- self.info("Created CORDUser %s for Subscriber %s" % (self.nodetemplate.name, sub.name))
+ self.info("Created CORDUser %s for Subscriber %s" % (self.obj_name, sub.name))
def update(self, obj):
pass
diff --git a/xos/tosca/resources/cdnprefix.py b/xos/tosca/resources/cdnprefix.py
index 5faaca8..8daf7fb 100644
--- a/xos/tosca/resources/cdnprefix.py
+++ b/xos/tosca/resources/cdnprefix.py
@@ -16,7 +16,7 @@
copyin_props = []
def get_xos_args(self):
- args = {"prefix": self.nodetemplate.name}
+ args = {"prefix": self.obj_name}
cp_name = self.get_requirement("tosca.relationships.MemberOfContentProvider")
if cp_name:
diff --git a/xos/tosca/resources/compute.py b/xos/tosca/resources/compute.py
index 37ba390..2af010a 100644
--- a/xos/tosca/resources/compute.py
+++ b/xos/tosca/resources/compute.py
@@ -39,7 +39,7 @@
nodetemplate = self.nodetemplate
if not name:
- name = nodetemplate.name
+ name = self.obj_name
args = {"name": name}
@@ -105,7 +105,7 @@
if scalable:
default_instances = scalable.get("default_instances",1)
for i in range(0, default_instances):
- name = "%s-%d" % (self.nodetemplate.name, i)
+ name = "%s-%d" % (self.obj_name, i)
existing_instances = Instance.objects.filter(name=name)
if existing_instances:
self.info("%s %s already exists" % (self.xos_model.__name__, name))
@@ -121,7 +121,7 @@
existing_instances = []
max_instances = scalable.get("max_instances",1)
for i in range(0, max_instances):
- name = "%s-%d" % (self.nodetemplate.name, i)
+ name = "%s-%d" % (self.obj_name, i)
existing_instances = existing_instances + list(Instance.objects.filter(name=name))
return existing_instances
else:
diff --git a/xos/tosca/resources/contentprovider.py b/xos/tosca/resources/contentprovider.py
index 06ca02e..66742ea 100644
--- a/xos/tosca/resources/contentprovider.py
+++ b/xos/tosca/resources/contentprovider.py
@@ -17,7 +17,7 @@
def get_xos_args(self):
sp_name = self.get_requirement("tosca.relationships.MemberOfServiceProvider", throw_exception=True)
sp = self.get_xos_object(ServiceProvider, name=sp_name)
- return {"name": self.nodetemplate.name,
+ return {"name": self.obj_name,
"serviceProvider": sp}
def can_delete(self, obj):
diff --git a/xos/tosca/resources/dashboardview.py b/xos/tosca/resources/dashboardview.py
index 9f7687c..3bce58d 100644
--- a/xos/tosca/resources/dashboardview.py
+++ b/xos/tosca/resources/dashboardview.py
@@ -17,6 +17,14 @@
def get_xos_args(self):
return super(XOSDashboardView, self).get_xos_args()
+ def postprocess(self, obj):
+ for deployment_name in self.get_requirements("tosca.relationships.SupportsDeployment"):
+ deployment = self.get_xos_object(Deployment, deployment_name)
+ if not deployment in obj.deployments.all():
+ print "attaching dashboardview %s to deployment %s" % (obj, deployment)
+ obj.deployments.add(deployment)
+ obj.save()
+
def can_delete(self, obj):
return super(XOSDashboardView, self).can_delete(obj)
diff --git a/xos/tosca/resources/deploymentrole.py b/xos/tosca/resources/deploymentrole.py
new file mode 100644
index 0000000..4339026
--- /dev/null
+++ b/xos/tosca/resources/deploymentrole.py
@@ -0,0 +1,29 @@
+# note: this module named xossite.py instead of site.py due to conflict with
+# /usr/lib/python2.7/site.py
+
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import User, Deployment, DeploymentRole
+
+from xosresource import XOSResource
+
+class XOSDeploymentRole(XOSResource):
+ provides = "tosca.nodes.DeploymentRole"
+ xos_model = DeploymentRole
+ name_field = "role"
+
+ def get_xos_args(self):
+ args = super(XOSDeploymentRole, self).get_xos_args()
+
+ return args
+
+ def delete(self, obj):
+ super(XOSDeploymentRole, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/node.py b/xos/tosca/resources/node.py
index 99e756f..128aaed 100644
--- a/xos/tosca/resources/node.py
+++ b/xos/tosca/resources/node.py
@@ -14,7 +14,7 @@
xos_model = Node
def get_xos_args(self):
- args = {"name": self.nodetemplate.name}
+ args = {"name": self.obj_name}
site = None
siteName = self.get_requirement("tosca.relationships.MemberOfSite", throw_exception=False)
@@ -44,9 +44,6 @@
obj.save()
def create(self):
- nodetemplate = self.nodetemplate
- sliceName = nodetemplate.name
-
xos_args = self.get_xos_args()
if not xos_args.get("site", None):
diff --git a/xos/tosca/resources/onosapp.py b/xos/tosca/resources/onosapp.py
index 72511b3..dccc8db 100644
--- a/xos/tosca/resources/onosapp.py
+++ b/xos/tosca/resources/onosapp.py
@@ -33,7 +33,7 @@
def get_existing_objs(self):
objs = ONOSApp.get_tenant_objects().all()
- objs = [x for x in objs if x.name == self.nodetemplate.name]
+ objs = [x for x in objs if x.name == self.obj_name]
return objs
def set_tenant_attr(self, obj, prop_name, value):
diff --git a/xos/tosca/resources/originserver.py b/xos/tosca/resources/originserver.py
index 196ce2e..46cf87e 100644
--- a/xos/tosca/resources/originserver.py
+++ b/xos/tosca/resources/originserver.py
@@ -15,18 +15,18 @@
name_field = "url"
copyin_props = []
- def nodetemplate_name_to_url(self):
- url = self.nodetemplate.name
+ def obj_name_to_url(self):
+ url = self.obj_name
if url.startswith("http_"):
url = url[5:]
return url
def get_existing_objs(self):
- url = self.nodetemplate_name_to_url()
+ url = self.obj_name_to_url()
return self.xos_model.objects.filter(**{self.name_field: url})
def get_xos_args(self):
- url = self.nodetemplate_name_to_url()
+ url = self.obj_name_to_url()
cp_name = self.get_requirement("tosca.relationships.MemberOfContentProvider", throw_exception=True)
cp = self.get_xos_object(ContentProvider, name=cp_name)
return {"url": url,
diff --git a/xos/tosca/resources/serviceprovider.py b/xos/tosca/resources/serviceprovider.py
index 8faec6c..2c9a167 100644
--- a/xos/tosca/resources/serviceprovider.py
+++ b/xos/tosca/resources/serviceprovider.py
@@ -17,7 +17,7 @@
def get_xos_args(self):
hpc_service_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=True)
hpc_service = self.get_xos_object(HpcService, name=hpc_service_name)
- return {"name": self.nodetemplate.name,
+ return {"name": self.obj_name,
"hpcService": hpc_service}
def can_delete(self, obj):
diff --git a/xos/tosca/resources/siterole.py b/xos/tosca/resources/siterole.py
new file mode 100644
index 0000000..abb1f0d
--- /dev/null
+++ b/xos/tosca/resources/siterole.py
@@ -0,0 +1,29 @@
+# note: this module named xossite.py instead of site.py due to conflict with
+# /usr/lib/python2.7/site.py
+
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import User, Deployment, SiteRole
+
+from xosresource import XOSResource
+
+class XOSSiteRole(XOSResource):
+ provides = "tosca.nodes.SiteRole"
+ xos_model = SiteRole
+ name_field = "role"
+
+ def get_xos_args(self):
+ args = super(XOSSiteRole, self).get_xos_args()
+
+ return args
+
+ def delete(self, obj):
+ super(XOSSiteRole, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/slice.py b/xos/tosca/resources/slice.py
index 22978a2..0add5ac 100644
--- a/xos/tosca/resources/slice.py
+++ b/xos/tosca/resources/slice.py
@@ -50,19 +50,6 @@
("tosca.relationships.PIPrivilege", "pi"), ("tosca.relationships.TechPrivilege", "tech") )
self.postprocess_privileges(SliceRole, SlicePrivilege, rolemap, obj, "slice")
- def create(self):
- nodetemplate = self.nodetemplate
- sliceName = nodetemplate.name
-
- xos_args = self.get_xos_args()
- slice = Slice(**xos_args)
- slice.caller = self.user
- slice.save()
-
- self.postprocess(slice)
-
- self.info("Created Slice '%s' on Site '%s'" % (str(slice), str(slice.site)))
-
def delete(self, obj):
if obj.instances.exists():
self.info("Slice %s has active instances; skipping delete" % obj.name)
diff --git a/xos/tosca/resources/slicerole.py b/xos/tosca/resources/slicerole.py
new file mode 100644
index 0000000..fc7d3f1
--- /dev/null
+++ b/xos/tosca/resources/slicerole.py
@@ -0,0 +1,29 @@
+# note: this module named xossite.py instead of site.py due to conflict with
+# /usr/lib/python2.7/site.py
+
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import User, Deployment, SliceRole
+
+from xosresource import XOSResource
+
+class XOSSliceRole(XOSResource):
+ provides = "tosca.nodes.SliceRole"
+ xos_model = SliceRole
+ name_field = "role"
+
+ def get_xos_args(self):
+ args = super(XOSSliceRole, self).get_xos_args()
+
+ return args
+
+ def delete(self, obj):
+ super(XOSSliceRole, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/tag.py b/xos/tosca/resources/tag.py
new file mode 100644
index 0000000..001cba8
--- /dev/null
+++ b/xos/tosca/resources/tag.py
@@ -0,0 +1,57 @@
+import importlib
+import os
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+from django.contrib.contenttypes.models import ContentType
+
+from core.models import Tag, Service
+
+from xosresource import XOSResource
+
+class XOSTag(XOSResource):
+ provides = "tosca.nodes.Tag"
+ xos_model = Tag
+ name_field = None
+ copyin_props = ("name", "value")
+
+ def get_xos_args(self, throw_exception=True):
+ args = super(XOSTag, self).get_xos_args()
+
+ # Find the Tosca object that this Tag is pointing to, and return its
+ # content_type and object_id, which will be used in the GenericForeignKey
+ # django relation.
+
+ target_name = self.get_requirement("tosca.relationships.TagsObject", throw_exception=throw_exception)
+ if target_name:
+ target_model = self.engine.name_to_xos_model(self.user, target_name)
+ args["content_type"] = ContentType.objects.get_for_model(target_model)
+ args["object_id"] = target_model.id
+
+ service_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+ if service_name:
+ args["service"] = self.get_xos_object(Service, name=service_name)
+
+ # To uniquely identify a Tag, we must know the object that it is attached
+ # to as well as the name of the Tag.
+
+ if ("content_type" not in args) or ("object_id" not in args) or ("name" not in args):
+ if throw_exception:
+ raise Exception("Tag must specify TagsObject requirement and Name property")
+
+ return args
+
+ def get_existing_objs(self):
+ args = self.get_xos_args(throw_exception=True)
+
+ return Tag.objects.filter(content_type=args["content_type"],
+ object_id=args["object_id"],
+ name=args["name"])
+
+ def postprocess(self, obj):
+ pass
+
+ def can_delete(self, obj):
+ return super(XOSTag, self).can_delete(obj)
+
diff --git a/xos/tosca/resources/tenantrole.py b/xos/tosca/resources/tenantrole.py
new file mode 100644
index 0000000..316a5a3
--- /dev/null
+++ b/xos/tosca/resources/tenantrole.py
@@ -0,0 +1,29 @@
+# note: this module named xossite.py instead of site.py due to conflict with
+# /usr/lib/python2.7/site.py
+
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import User, Deployment, TenantRole
+
+from xosresource import XOSResource
+
+class XOSTenantRole(XOSResource):
+ provides = "tosca.nodes.TenantRole"
+ xos_model = TenantRole
+ name_field = "role"
+
+ def get_xos_args(self):
+ args = super(XOSTenantRole, self).get_xos_args()
+
+ return args
+
+ def delete(self, obj):
+ super(XOSTenantRole, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/user.py b/xos/tosca/resources/user.py
index 8587c89..55c0423 100644
--- a/xos/tosca/resources/user.py
+++ b/xos/tosca/resources/user.py
@@ -25,7 +25,7 @@
return args
def get_existing_objs(self):
- return self.xos_model.objects.filter(email = self.nodetemplate.name)
+ return self.xos_model.objects.filter(email = self.obj_name)
def postprocess(self, obj):
rolemap = ( ("tosca.relationships.AdminPrivilege", "admin"), ("tosca.relationships.AccessPrivilege", "access"),
@@ -62,12 +62,12 @@
udv.save()
def create(self):
- nodetemplate = self.nodetemplate
-
xos_args = self.get_xos_args()
if not xos_args.get("site",None):
raise Exception("Site name must be specified when creating user")
+ if ("firstname" not in xos_args) or ("lastname" not in xos_args):
+ raise Exception("firstname and lastname must be specified when creating user")
user = User(**xos_args)
user.save()
diff --git a/xos/tosca/resources/vtnservice.py b/xos/tosca/resources/vtnservice.py
index f0940d6..2a5738f 100644
--- a/xos/tosca/resources/vtnservice.py
+++ b/xos/tosca/resources/vtnservice.py
@@ -12,5 +12,4 @@
class XOSVTNService(XOSService):
provides = "tosca.nodes.VTNService"
xos_model = VTNService
- copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber", 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits']
-
+ copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber", 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword']
diff --git a/xos/tosca/resources/xosresource.py b/xos/tosca/resources/xosresource.py
index 7a6c194..e70cfa9 100644
--- a/xos/tosca/resources/xosresource.py
+++ b/xos/tosca/resources/xosresource.py
@@ -19,6 +19,17 @@
self.nodetemplate = nodetemplate
self.engine = engine
+ @property
+ def full_name(self):
+ return self.nodetemplate.name
+
+ @property
+ def obj_name(self):
+ if "#" in self.nodetemplate.name:
+ return self.nodetemplate.name.split("#",1)[1]
+ else:
+ return self.nodetemplate.name
+
def get_all_required_node_names(self):
results = []
for reqs in self.nodetemplate.requirements:
@@ -38,7 +49,7 @@
results.append(v["node"])
if (not results) and throw_exception:
- raise Exception("Failed to find requirement in %s using relationship %s" % (self.nodetemplate.name, relationship_name))
+ raise Exception("Failed to find requirement in %s using relationship %s" % (self.full_name, relationship_name))
return results
@@ -75,7 +86,7 @@
return objs[0]
def get_existing_objs(self):
- return self.xos_model.objects.filter(**{self.name_field: self.nodetemplate.name})
+ return self.xos_model.objects.filter(**{self.name_field: self.obj_name})
def get_model_class_name(self):
return self.xos_model.__name__
@@ -84,19 +95,19 @@
existing_objs = self.get_existing_objs()
if existing_objs:
if self.get_property_default("no-update", False):
- self.info("%s %s already exists. Skipping update due to 'no-update' property" % (self.get_model_class_name(), self.nodetemplate.name))
+ self.info("%s:%s (%s) already exists. Skipping update due to 'no-update' property" % (self.get_model_class_name(), self.obj_name, self.full_name))
else:
- self.info("%s %s already exists" % (self.get_model_class_name(), self.nodetemplate.name))
+ self.info("%s:%s (%s) already exists" % (self.get_model_class_name(), self.obj_name, self.full_name))
self.update(existing_objs[0])
else:
if self.get_property_default("no-create", False):
- self.info("%s %s does not exist, but 'no-create' is specified" % (self.get_model_class_name(), self.nodetemplate.name))
+ self.info("%s:%s (%s) does not exist, but 'no-create' is specified" % (self.get_model_class_name(), self.obj_name, self.full_name))
else:
self.create()
def can_delete(self, obj):
if self.get_property_default("no-delete",False):
- self.info("%s %s is marked 'no-delete'. Skipping delete." % (self.get_model_class_name(), self.nodetemplate.name))
+ self.info("%s:%s %s is marked 'no-delete'. Skipping delete." % (self.get_model_class_name(), self.obj_name, self.full_name))
return False
return True
@@ -170,7 +181,7 @@
args = {}
if self.name_field:
- args[self.name_field] = self.nodetemplate.name
+ args[self.name_field] = self.obj_name
# copy simple string properties from the template into the arguments
for prop in self.copyin_props:
diff --git a/xos/tosca/resources/xossite.py b/xos/tosca/resources/xossite.py
index 616e397..9b03bc5 100644
--- a/xos/tosca/resources/xossite.py
+++ b/xos/tosca/resources/xossite.py
@@ -19,9 +19,9 @@
def get_xos_args(self):
display_name = self.get_property("display_name")
if not display_name:
- display_name = self.nodetemplate.name
+ display_name = self.obj_name
- args = {"login_base": self.nodetemplate.name,
+ args = {"login_base": self.obj_name,
"name": display_name}
# copy simple string properties from the template into the arguments
@@ -33,7 +33,7 @@
return args
def get_existing_objs(self):
- return self.xos_model.objects.filter(login_base = self.nodetemplate.name)
+ return self.xos_model.objects.filter(login_base = self.obj_name)
def postprocess(self, obj):
results = []
@@ -68,20 +68,6 @@
sitedep.save()
self.info("Created SiteDeployment from %s to %s" % (str(obj), str(deployment)))
- def create(self):
- nodetemplate = self.nodetemplate
- siteName = nodetemplate.name
-
- xos_args = self.get_xos_args()
-
- site = Site(**xos_args)
- site.caller = self.user
- site.save()
-
- self.postprocess(site)
-
- self.info("Created Site '%s'" % (str(site), ))
-
def delete(self, obj):
if obj.slices.exists():
self.info("Site %s has active slices; skipping delete" % obj.name)
diff --git a/xos/tosca/samples/slicetag.yaml b/xos/tosca/samples/slicetag.yaml
new file mode 100644
index 0000000..ec064e3
--- /dev/null
+++ b/xos/tosca/samples/slicetag.yaml
@@ -0,0 +1,35 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Setup CORD-related services -- vOLT, vCPE, vBNG.
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+ mysite_vsg:
+ type: tosca.nodes.Slice
+ properties:
+ no-create: True
+ no-delete: True
+ no-update: True
+
+ service_vsg:
+ type: tosca.nodes.Service
+ properties:
+ no-create: True
+ no-delete: True
+ no-update: True
+
+ mysite_vsg_foobar_tag:
+ type: tosca.nodes.Tag
+ properties:
+ name: foobar
+ value: xyz
+ requirements:
+ - target:
+ node: mysite_vsg
+ relationship: tosca.relationships.TagsObject
+ - service:
+ node: service_vsg
+ relationship: tosca.relationships.MemberOfService