blob: efce8296017c75826e59bc0444f25163ce6f3df5 [file] [log] [blame]
import os
import pdb
import sys
import tempfile
import traceback
sys.path.append("/opt/tosca")
from translator.toscalib.tosca_template import ToscaTemplate
from core.models import Slice,Instance,User,Flavor,Node,Image
from nodeselect import XOSNodeSelector
from imageselect import XOSImageSelector
import resources
class XOSTosca(object):
def __init__(self, tosca_yaml, parent_dir=None, log_to_console = False):
# TOSCA will look for imports using a relative path from where the
# template file is located, so we have to put the template file
# in a specific place.
if not parent_dir:
parent_dir = os.getcwd()
tmp_pathname = None
try:
(tmp_handle, tmp_pathname) = tempfile.mkstemp(dir=parent_dir)
os.write(tmp_handle, tosca_yaml)
os.close(tmp_handle)
self.template = ToscaTemplate(tmp_pathname)
except:
traceback.print_exc()
raise
finally:
if tmp_pathname:
os.remove(tmp_pathname)
self.log_to_console = log_to_console
self.log_msgs = []
self.compute_dependencies()
self.deferred_sync = []
self.ordered_nodetemplates = []
self.ordered_names = self.topsort_dependencies()
self.log("ordered_names: %s" % self.ordered_names)
for name in self.ordered_names:
if name in self.nodetemplates_by_name:
self.ordered_nodetemplates.append(self.nodetemplates_by_name[name])
#pdb.set_trace()
def log(self, msg):
if self.log_to_console:
print msg
self.log_msgs.append(msg)
def compute_dependencies(self):
nodetemplates_by_name = {}
for nodetemplate in self.template.nodetemplates:
nodetemplates_by_name[nodetemplate.name] = nodetemplate
self.nodetemplates_by_name = nodetemplates_by_name
for nodetemplate in self.template.nodetemplates:
nodetemplate.dependencies = []
nodetemplate.dependencies_names = []
for reqs in nodetemplate.requirements:
for (k,v) in reqs.items():
name = v["node"]
if (name in nodetemplates_by_name):
nodetemplate.dependencies.append(nodetemplates_by_name[name])
nodetemplate.dependencies_names.append(name)
# go another level deep, as our requirements can have requirements...
for sd_req in v.get("requirements",[]):
for (sd_req_k, sd_req_v) in sd_req.items():
name = sd_req_v["node"]
if (name in nodetemplates_by_name):
nodetemplate.dependencies.append(nodetemplates_by_name[name])
nodetemplate.dependencies_names.append(name)
def topsort_dependencies(self):
# stolen from observer
g = self.nodetemplates_by_name
# Get set of all nodes, including those without outgoing edges
keys = set(g.keys())
values = set({})
for v in g.values():
values=values | set(v.dependencies_names)
all_nodes=list(keys|values)
steps = all_nodes
# Final order
order = []
# DFS stack, not using recursion
stack = []
# Unmarked set
unmarked = all_nodes
# visiting = [] - skip, don't expect 1000s of nodes, |E|/|V| is small
while unmarked:
stack.insert(0,unmarked[0]) # push first unmarked
while (stack):
n = stack[0]
add = True
try:
for m in g[n].dependencies_names:
if (m in unmarked):
add = False
stack.insert(0,m)
except KeyError:
pass
if (add):
if (n in steps and n not in order):
order.append(n)
item = stack.pop(0)
try:
unmarked.remove(item)
except ValueError:
pass
noorder = list(set(steps) - set(order))
return order + noorder
def execute(self, user):
for nodetemplate in self.ordered_nodetemplates:
self.execute_nodetemplate(user, nodetemplate)
for obj in self.deferred_sync:
self.log("Saving deferred sync obj %s" % obj)
obj.no_sync = False
obj.save()
def execute_nodetemplate(self, user, nodetemplate):
if nodetemplate.type in resources.resources:
cls = resources.resources[nodetemplate.type]
#print "work on", cls.__name__, nodetemplate.name
obj = cls(user, nodetemplate, self)
obj.create_or_update()
self.deferred_sync = self.deferred_sync + obj.deferred_sync
def destroy(self, user):
nodetemplates = self.ordered_nodetemplates
models = []
for nodetemplate in nodetemplates:
if nodetemplate.type in resources.resources:
cls = resources.resources[nodetemplate.type]
obj = cls(user, nodetemplate, self)
for model in obj.get_existing_objs():
models.append( (obj, model) )
models.reverse()
for (resource,model) in models:
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]