Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 87c96b4..b1f6873 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -3,7 +3,10 @@
node_types:
tosca.nodes.Service:
derived_from: tosca.nodes.Root
-
+
+ tosca.nodes.Site:
+ derived_from: tosca.nodes.Root
+
tosca.nodes.Slice:
derived_from: tosca.nodes.Root
properties:
@@ -17,5 +20,8 @@
tosca.relationships.MemberOfService:
derived_from: tosca.relationships.Root
+ tosca.relationships.MemberOfSite:
+ derived_from: tosca.relationships.Root
+
tosca.relationships.TenantOfService:
derived_from: tosca.relationships.Root
diff --git a/xos/tosca/engine.py b/xos/tosca/engine.py
index 4f74d28..e33d0f0 100644
--- a/xos/tosca/engine.py
+++ b/xos/tosca/engine.py
@@ -9,6 +9,8 @@
from nodeselect import XOSNodeSelector
from imageselect import XOSImageSelector
+import resources
+
class XOSTosca(object):
def __init__(self, tosca_yaml, parent_dir=None):
# TOSCA will look for imports using a relative path from where the
@@ -32,75 +34,13 @@
for nodetemplate in self.template.nodetemplates:
self.execute_nodetemplate(user, nodetemplate)
- def select_compute_node(self, user, v):
- mem_size = v.get_property_value("mem_size")
- num_cpus = v.get_property_value("num_cpus")
- disk_size = v.get_property_value("disk_size")
-
- # TODO: pick flavor based on parameters
- flavor = Flavor.objects.get(name="m1.small")
-
- compute_node = XOSNodeSelector(user, mem_size=mem_size, num_cpus=num_cpus, disk_size=disk_size).get_nodes(1)[0]
-
- return (compute_node, flavor)
-
- def select_image(self, user, v):
- distribution = v.get_property_value("distribution")
- version = v.get_property_value("version")
- type = v.get_property_value("type")
- architecture = v.get_property_value("architecture")
-
- return XOSImageSelector(user, distribution=distribution, version=version, type=type, architecture=architecture).get_image()
-
def execute_nodetemplate(self, user, nodetemplate):
- if (nodetemplate.type == "tosca.nodes.Slice"):
- return
+ if nodetemplate.type in resources.resources:
+ cls = resources.resources[nodetemplate.type]
+ obj = cls(user, nodetemplate)
+ obj.save_if_dirty()
- if (nodetemplate.type == "tosca.nodes.Service"):
- return
- if (nodetemplate.type != "tosca.nodes.Compute"):
- raise Exception("I Don't know how to deal with %s" % nodetemplate.type)
-
- host=None
- flavor=None
- image=None
-
- sliceName = None
- for reqs in nodetemplate.requirements:
- for (k,v) in reqs.items():
- print v
- if (v["relationship"] == "tosca.relationships.MemberOfSlice"):
- sliceName = v["node"]
- if not sliceName:
- raise Exception("No slice requirement for node %s" % nodetemplate.name)
-
- slice = Slice.objects.filter(name=sliceName)
- if not slice:
- raise Exception("Could not find slice %s" % sliceName)
- slice = slice[0]
-
- capabilities = nodetemplate.get_capabilities()
- for (k,v) in capabilities.items():
- if (k=="host"):
- (compute_node, flavor) = self.select_compute_node(user, v)
- elif (k=="os"):
- image = self.select_image(user, v)
-
- if not compute_node:
- raise Exception("Failed to pick a host")
- if not image:
- raise Exception("Failed to pick an image")
- if not flavor:
- raise Exception("Failed to pick a flavor")
-
- sliver = Sliver(deployment = compute_node.site_deployment.deployment,
- node = compute_node,
- flavor = flavor,
- slice = slice,
- image = image)
- sliver.caller = user
- print "XXX save sliver" #sliver.save()
diff --git a/xos/tosca/resources/__init__.py b/xos/tosca/resources/__init__.py
new file mode 100644
index 0000000..fb0a695
--- /dev/null
+++ b/xos/tosca/resources/__init__.py
@@ -0,0 +1,37 @@
+from xosresource import XOSResource
+from django.conf.urls import patterns, url
+from rest_framework.routers import DefaultRouter
+import os, sys
+import inspect
+import importlib
+
+# XXX based on core/dashboard/views/__init__.py
+
+# Find all modules in the current directory that have descendents of the XOSResource
+# object, and add them as globals to this module. Also, build up a list of urls
+# based on the "url" field of the view classes.
+
+resources = {}
+
+sys_path_save = sys.path
+try:
+ # __import__() and importlib.import_module() both import modules from
+ # sys.path. So we make sure that the path where we can find the views is
+ # the first thing in sys.path.
+ view_dir = os.path.dirname(os.path.abspath(__file__))
+ sys.path = [view_dir] + sys.path
+ view_urls = []
+ for fn in os.listdir(view_dir):
+ pathname = os.path.join(view_dir,fn)
+ if os.path.isfile(pathname) and fn.endswith(".py") and (fn!="__init__.py"):
+ module = __import__(fn[:-3])
+ for classname in dir(module):
+ c = getattr(module, classname, None)
+
+ if inspect.isclass(c) and (getattr(c,"xos_base_class",None)=="XOSResource") and (classname not in globals()):
+ provides = getattr(c, "provides", None)
+ if provides:
+ globals()[classname] = c
+ resources[provides] = c
+finally:
+ sys.path = sys_path_save
diff --git a/xos/tosca/resources/compute.py b/xos/tosca/resources/compute.py
new file mode 100644
index 0000000..71c7926
--- /dev/null
+++ b/xos/tosca/resources/compute.py
@@ -0,0 +1,76 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import Slice,Sliver,User,Flavor,Node,Image
+from nodeselect import XOSNodeSelector
+from imageselect import XOSImageSelector
+
+from xosresource import XOSResource
+
+class XOSCompute(XOSResource):
+ provides = "tosca.nodes.Compute"
+
+ def select_compute_node(self, user, v):
+ mem_size = v.get_property_value("mem_size")
+ num_cpus = v.get_property_value("num_cpus")
+ disk_size = v.get_property_value("disk_size")
+
+ # TODO: pick flavor based on parameters
+ flavor = Flavor.objects.get(name="m1.small")
+
+ compute_node = XOSNodeSelector(user, mem_size=mem_size, num_cpus=num_cpus, disk_size=disk_size).get_nodes(1)[0]
+
+ return (compute_node, flavor)
+
+ def select_image(self, user, v):
+ distribution = v.get_property_value("distribution")
+ version = v.get_property_value("version")
+ type = v.get_property_value("type")
+ architecture = v.get_property_value("architecture")
+
+ return XOSImageSelector(user, distribution=distribution, version=version, type=type, architecture=architecture).get_image()
+
+ def process_nodetemplate(self):
+ nodetemplate = self.nodetemplate
+
+ host=None
+ flavor=None
+ image=None
+
+ sliceName = self.get_requirement("tosca.relationships.MemberOfSlice", throw_exception=True)
+ slice = self.get_xos_object(Slice, name=sliceName)
+
+ capabilities = nodetemplate.get_capabilities()
+ for (k,v) in capabilities.items():
+ if (k=="host"):
+ (compute_node, flavor) = self.select_compute_node(self.user, v)
+ elif (k=="os"):
+ image = self.select_image(self.user, v)
+
+ if not compute_node:
+ raise Exception("Failed to pick a host")
+ if not image:
+ raise Exception("Failed to pick an image")
+ if not flavor:
+ raise Exception("Failed to pick a flavor")
+
+ sliver = Sliver(deployment = compute_node.site_deployment.deployment,
+ node = compute_node,
+ flavor = flavor,
+ slice = slice,
+ image = image)
+ sliver.caller = self.user
+
+ self.resource = sliver
+ self.dirty = True
+
+ self.info("Created Sliver '%s' on node '%s' using flavor '%s' and image '%s'" %
+ (str(sliver), str(compute_node), str(flavor), str(image)))
+
+ def save(self):
+ self.resource.save()
+
diff --git a/xos/tosca/resources/slice.py b/xos/tosca/resources/slice.py
new file mode 100644
index 0000000..6fdfd35
--- /dev/null
+++ b/xos/tosca/resources/slice.py
@@ -0,0 +1,37 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import Slice,User,Site
+
+from xosresource import XOSResource
+
+class XOSSlice(XOSResource):
+ provides = "tosca.nodes.Slice"
+
+ def process_nodetemplate(self):
+ nodetemplate = self.nodetemplate
+ sliceName = nodetemplate.name
+
+ existing_slices = Slice.objects.filter(name=sliceName)
+ if existing_slices:
+ self.info("Slice %s already exists" % sliceName)
+
+ site_name = self.get_requirement("tosca.relationships.MemberOfSite", throw_exception=True)
+ site = self.get_xos_object(Site, login_base=site_name)
+
+ slice = Slice(name = sliceName,
+ site = site)
+ slice.caller = self.user
+
+ self.resource = slice
+ self.dirty = True
+
+ self.info("Created Slice '%s' on Site '%s'" % (str(slice), str(site)))
+
+ def save(self):
+ self.resource.save()
+
diff --git a/xos/tosca/resources/xosresource.py b/xos/tosca/resources/xosresource.py
new file mode 100644
index 0000000..05adcbe
--- /dev/null
+++ b/xos/tosca/resources/xosresource.py
@@ -0,0 +1,44 @@
+class XOSResource(object):
+ xos_base_class = "XOSResource"
+ provides = None
+
+ def __init__(self, user, nodetemplate):
+ self.dirty = False
+ self.user = user
+ self.nodetemplate = nodetemplate
+ self.process_nodetemplate()
+
+ def get_requirement(self, relationship_name, throw_exception=False):
+ """ helper to search the list of requirements for a particular relationship
+ type.
+ """
+ for reqs in self.nodetemplate.requirements:
+ for (k,v) in reqs.items():
+ if (v["relationship"] == relationship_name):
+ return v["node"]
+
+ if throw_exception:
+ raise Exception("Failed to find requirement in %s using relationship %s" % (self.nodetemplate.name, relationship_name))
+
+ return None
+
+ def get_xos_object(self, cls, **kwargs):
+ objs = cls.objects.filter(**kwargs)
+ if not objs:
+ raise Exception("Failed to find %s filtered by %s" % (cls.__name__, str(kwargs)))
+ return objs[0]
+
+ def process_nodetemplate(self):
+ pass
+
+ def save(self):
+ pass
+
+ def save_if_dirty(self):
+ if self.dirty:
+ self.save()
+ self.dirty=False
+
+ def info(self, s):
+ print s
+
diff --git a/xos/tosca/samples/one_instance.yaml b/xos/tosca/samples/one_instance.yaml
index 968c999..f8919ed 100644
--- a/xos/tosca/samples/one_instance.yaml
+++ b/xos/tosca/samples/one_instance.yaml
@@ -7,8 +7,15 @@
topology_template:
node_templates:
+ mysite:
+ type: tosca.nodes.Site
+
mysite_tosca:
type: tosca.nodes.Slice
+ requirements:
+ - slice:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
my_server:
type: tosca.nodes.Compute