Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/tosca/all_samples.sh b/xos/tosca/all_samples.sh
new file mode 100755
index 0000000..9b8f189
--- /dev/null
+++ b/xos/tosca/all_samples.sh
@@ -0,0 +1,14 @@
+# cleanup phase
+for f in samples/*.yaml; do
+ echo --------------------------------------------------
+ echo destroy $f
+ python ./destroy.py scott@onlab.us $f
+done
+
+for f in samples/*.yaml; do
+ echo --------------------------------------------------
+ echo run $f
+ python ./run.py scott@onlab.us $f
+ echo destroy $f
+ python ./destroy.py scott@onlab.us $f
+done
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index ebe1e05..044f281 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -1,6 +1,20 @@
tosca_definitions_version: tosca_simple_yaml_1_0
node_types:
+ # I wanted to make this the base of all XOS node types, but doing so throws
+ # InvalidTypeError: Type "tosca.nodes.XOS" is not a valid type
+ tosca.nodes.XOS:
+ derived_from: tosca.nodes.Root
+ 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
+
tosca.nodes.Service:
derived_from: tosca.nodes.Root
capabilities:
@@ -15,6 +29,42 @@
# default: false
# description: prevent this resource from being deleted
+ tosca.nodes.User:
+ derived_from: tosca.nodes.Root
+
+ capabilities:
+ user:
+ type: tosca.capabilities.xos.User
+
+ properties:
+ password:
+ type: string
+ required: true
+ firstname:
+ type: string
+ required: true
+ lastname:
+ type: string
+ required: true
+ phone:
+ type: string
+ required: false
+ user_url:
+ type: string
+ required: false
+ public_key:
+ type: string
+ required: false
+ is_active:
+ type: boolean
+ default: true
+ is_admin:
+ type: boolean
+ default: false
+ login_page:
+ type: string
+ required: false
+
tosca.nodes.NetworkTemplate:
derived_from: tosca.nodes.Root
@@ -160,15 +210,31 @@
tosca.relationships.ConnectsToNetwork:
derived_from: tosca.relationships.Root
- valid_target_types: [ tosca.capabilitys.xos.Network ]
+ valid_target_types: [ tosca.capabilities.xos.Network ]
# tosca.relationships.OwnsNetwork:
# derived_from: tosca.relationships.Root
-# valid_target_types: [ tosca.capabilitys.xos.Network ]
+# valid_target_types: [ tosca.capabilities.xos.Network ]
tosca.relationships.UsesNetworkTemplate:
derived_from: tosca.relationships.Root
- valid_target_types: [ tosca.capabilitys.xos.NetworkTemplate ]
+ valid_target_types: [ tosca.capabilities.xos.NetworkTemplate ]
+
+ tosca.relationships.AdminPrivilege:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabiltys.xos.Site ]
+
+ tosca.relationships.AccessPrivilege:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabiltys.xos.Site ]
+
+ tosca.relationships.PIPrivilege:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabiltys.xos.Site ]
+
+ tosca.relationships.TechPrivilege:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabiltys.xos.Site ]
tosca.capabilities.xos.Service:
derived_from: tosca.capabilities.Root
@@ -197,3 +263,7 @@
tosca.capabilities.xos.Network:
derived_from: tosca.capabilities.Root
description: An XOS network
+
+ tosca.capabilities.xos.User:
+ derived_from: tosca.capabilities.Root
+ description: An XOS user
diff --git a/xos/tosca/engine.py b/xos/tosca/engine.py
index 5417cbc..a0d917d 100644
--- a/xos/tosca/engine.py
+++ b/xos/tosca/engine.py
@@ -122,7 +122,7 @@
if nodetemplate.type in resources.resources:
cls = resources.resources[nodetemplate.type]
#print "work on", cls.__name__, nodetemplate.name
- obj = cls(user, nodetemplate)
+ obj = cls(user, nodetemplate, self)
obj.create_or_update()
def destroy(self, user):
@@ -131,7 +131,7 @@
for nodetemplate in nodetemplates:
if nodetemplate.type in resources.resources:
cls = resources.resources[nodetemplate.type]
- obj = cls(user, nodetemplate)
+ obj = cls(user, nodetemplate, self)
for model in obj.get_existing_objs():
models.append( (obj, model) )
models.reverse()
@@ -139,3 +139,22 @@
print "destroying", model
resource.delete(model)
+ def name_to_xos_class(self, user, name):
+ nt = self.nodetemplates_by_name.get(name)
+ if not nt:
+ raise Exception("failed to find nodetemplate %s" % name)
+
+ cls = resources.resources.get(nt.type)
+ if not cls:
+ raise Exception("nodetemplate %s's type does not resolve to a known resource type" % name)
+
+ return (nt, cls, cls.xos_model)
+
+ def name_to_xos_model(self, user, name):
+ (nt, cls, model_class) = self.name_to_xos_class(user, name)
+ obj = cls(user, nt, self)
+ existing_objs = obj.get_existing_objs()
+ if not existing_objs:
+ raise Exception("failed to find xos %s %s" % (cls.__name__, name))
+ return existing_objs[0]
+
diff --git a/xos/tosca/resources/slice.py b/xos/tosca/resources/slice.py
index 054111c..073e205 100644
--- a/xos/tosca/resources/slice.py
+++ b/xos/tosca/resources/slice.py
@@ -5,7 +5,7 @@
sys.path.append("/opt/tosca")
from translator.toscalib.tosca_template import ToscaTemplate
-from core.models import Slice,User,Site,Network,NetworkSlice
+from core.models import Slice,User,Site,Network,NetworkSlice,SliceRole,SlicePrivilege
from xosresource import XOSResource
@@ -27,6 +27,17 @@
ns.save()
self.info("Added network connection from '%s' to '%s'" % (str(obj), str(net)))
+ rolemap = ( ("tosca.relationships.AdminPrivilege", "admin"), ("tosca.relationships.AccessPrivilege", "access"),
+ ("tosca.relationships.PIPrivilege", "pi"), ("tosca.relationships.TechPrivilege", "tech") )
+ for (rel, role) in rolemap:
+ for email in self.get_requirements(rel):
+ role = self.get_xos_object(SliceRole, role=role)
+ user = self.get_xos_object(User, email=email)
+ if not SlicePrivilege.objects.filter(user=user, role=role, slice=obj):
+ sp = SlicePrivilege(user=user, role=role, slice=obj)
+ sp.save()
+ self.info("Added slice privilege on %s role %s for %s" % (str(obj), str(role), str(user)))
+
def create(self):
nodetemplate = self.nodetemplate
sliceName = nodetemplate.name
diff --git a/xos/tosca/resources/user.py b/xos/tosca/resources/user.py
new file mode 100644
index 0000000..125df4f
--- /dev/null
+++ b/xos/tosca/resources/user.py
@@ -0,0 +1,75 @@
+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, Site, SiteRole, SliceRole, SlicePrivilege, SitePrivilege
+
+from xosresource import XOSResource
+
+class XOSUser(XOSResource):
+ provides = "tosca.nodes.User"
+ xos_model = User
+
+ def get_xos_args(self):
+ args = {"email": self.nodetemplate.name}
+
+ # copy simple string properties from the template into the arguments
+ for prop in ["password", "firstname", "lastname", "phone", "user_url", "public_key", "is_active", "is_admin", "login_page"]:
+ v = self.get_property(prop)
+ if v:
+ args[prop] = v
+
+ site_name = self.get_requirement("tosca.relationships.MemberOfSite")
+ if site_name:
+ args["site"] = self.get_xos_object(Site, login_base=site_name)
+
+ return args
+
+ def get_existing_objs(self):
+ return self.xos_model.objects.filter(email = self.nodetemplate.name)
+
+ def postprocess(self, obj):
+ rolemap = ( ("tosca.relationships.AdminPrivilege", "admin"), ("tosca.relationships.AccessPrivilege", "access"),
+ ("tosca.relationships.PIPrivilege", "pi"), ("tosca.relationships.TechPrivilege", "tech") )
+ for (rel, role) in rolemap:
+ for obj_name in self.get_requirements(rel):
+ dest = self.engine.name_to_xos_model(self.user, obj_name)
+ if dest.__class__.__name__ == "Slice":
+ role_obj = self.get_xos_object(SliceRole, role=role)
+ if not SlicePrivilege.objects.filter(user=user, role=role_obj, slice=dest):
+ sp = SlicePrivilege(user=obj, role=role_obj, slice=dest)
+ sp.save()
+ self.info("Added slice privilege on %s role %s for %s" % (str(dest), str(role), str(obj)))
+ elif dest.__class__.__name__ == "Site":
+ role_obj = self.get_xos_object(SiteRole, role=role)
+ if not SitePrivilege.objects.filter(user=obj, role=role_obj, site=dest):
+ sp = SitePrivilege(user=obj, role=role_obj, site=dest)
+ sp.save()
+ self.info("Added site privilege on %s role %s for %s" % (str(dest), str(role), str(obj)))
+
+ 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")
+
+ user = User(**xos_args)
+ user.save()
+
+ self.postprocess(user)
+
+ self.info("Created User '%s'" % (str(user), ))
+
+ def delete(self, obj):
+ if obj.slices.exists():
+ self.info("User %s has active slices; skipping delete" % obj.name)
+ return
+ super(XOSUser, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/xosresource.py b/xos/tosca/resources/xosresource.py
index 756aaf8..a0426cf 100644
--- a/xos/tosca/resources/xosresource.py
+++ b/xos/tosca/resources/xosresource.py
@@ -5,10 +5,11 @@
xos_model = None
provides = None
- def __init__(self, user, nodetemplate):
+ def __init__(self, user, nodetemplate, engine):
self.dirty = False
self.user = user
self.nodetemplate = nodetemplate
+ self.engine = engine
def get_all_required_node_names(self):
results = []
diff --git a/xos/tosca/resources/xossite.py b/xos/tosca/resources/xossite.py
index 4265338..fe0e256 100644
--- a/xos/tosca/resources/xossite.py
+++ b/xos/tosca/resources/xossite.py
@@ -19,7 +19,7 @@
def get_xos_args(self):
display_name = self.get_property("display_name")
if not display_name:
- display_name = nodetemplate.name
+ display_name = self.nodetemplate.name
args = {"login_base": self.nodetemplate.name,
"name": display_name}
diff --git a/xos/tosca/samples/privileges.yaml b/xos/tosca/samples/privileges.yaml
new file mode 100644
index 0000000..d15f343
--- /dev/null
+++ b/xos/tosca/samples/privileges.yaml
@@ -0,0 +1,60 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Make some network templates
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+ mysite:
+ type: tosca.nodes.Site
+
+ johndoe@foo.bar:
+ type: tosca.nodes.User
+ properties:
+ password: letmein
+ firstname: john
+ lastname: doe
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+ # Site privilege must always be specified in user objects, since
+ # user depends on site.
+ - privilege:
+ node: mysite
+ relationship: tosca.relationships.PIPrivilege
+
+ janedoe@foo.bar:
+ type: tosca.nodes.User
+ properties:
+ password: letmein
+ firstname: john
+ lastname: doe
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+ - privilege:
+ node: mysite
+ relationship: tosca.relationships.TechPrivilege
+
+ privsite:
+ type: tosca.nodes.Site
+
+ privsite_slice1:
+ type: tosca.nodes.Slice
+ requirements:
+ - slice:
+ node: privsite
+ relationship: tosca.relationships.MemberOfSite
+ # Slice privileges must always be specified in slice objects, since
+ # slice depends on user.
+ - privilege:
+ node: johndoe@foo.bar
+ relationship: tosca.relationships.AdminPrivilege
+ - privilege:
+ node: janedoe@foo.bar
+ relationship: tosca.relationships.AccessPrivilege
+
diff --git a/xos/tosca/samples/users.yaml b/xos/tosca/samples/users.yaml
new file mode 100644
index 0000000..20da611
--- /dev/null
+++ b/xos/tosca/samples/users.yaml
@@ -0,0 +1,39 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Make some network templates
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+ mysite:
+ type: tosca.nodes.Site
+
+ johndoe@foo.bar:
+ type: tosca.nodes.User
+ properties:
+ password: letmein
+ firstname: john
+ lastname: doe
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+
+ janedoe@foo.bar:
+ type: tosca.nodes.User
+ properties:
+ password: letmeintoo
+ firstname: jane
+ lastname: doe
+ phone: 111-222-3333
+ user_url: http://janedoe/
+ public_key: asdlfkjasldkfjasldkjfhaslkdjfhglaskdjfhlaksjdhfkasdfasdf
+ is_active: true
+ is_admin: true
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+