blob: efce8296017c75826e59bc0444f25163ce6f3df5 [file] [log] [blame]
Scott Baker66566722015-07-27 17:42:39 -07001import os
2import pdb
3import sys
4import tempfile
Scott Bakere08b4562015-08-11 17:23:52 -07005import traceback
6
Scott Baker66566722015-07-27 17:42:39 -07007sys.path.append("/opt/tosca")
8from translator.toscalib.tosca_template import ToscaTemplate
9
Tony Mackd8515472015-08-19 11:58:18 -040010from core.models import Slice,Instance,User,Flavor,Node,Image
Scott Bakerefa6ea42015-07-31 11:48:45 -070011from nodeselect import XOSNodeSelector
Scott Baker1f9d4512015-08-03 09:56:35 -070012from imageselect import XOSImageSelector
Scott Baker66566722015-07-27 17:42:39 -070013
Scott Baker3841b372015-08-03 14:20:31 -070014import resources
15
Scott Baker66566722015-07-27 17:42:39 -070016class XOSTosca(object):
Scott Bakere08b4562015-08-11 17:23:52 -070017 def __init__(self, tosca_yaml, parent_dir=None, log_to_console = False):
Scott Baker7e472dd2015-07-31 12:30:28 -070018 # TOSCA will look for imports using a relative path from where the
19 # template file is located, so we have to put the template file
20 # in a specific place.
21 if not parent_dir:
22 parent_dir = os.getcwd()
23
Scott Bakere08b4562015-08-11 17:23:52 -070024 tmp_pathname = None
Scott Baker66566722015-07-27 17:42:39 -070025 try:
Scott Baker7e472dd2015-07-31 12:30:28 -070026 (tmp_handle, tmp_pathname) = tempfile.mkstemp(dir=parent_dir)
Scott Baker66566722015-07-27 17:42:39 -070027 os.write(tmp_handle, tosca_yaml)
28 os.close(tmp_handle)
29
30 self.template = ToscaTemplate(tmp_pathname)
Scott Bakere08b4562015-08-11 17:23:52 -070031 except:
32 traceback.print_exc()
33 raise
Scott Baker66566722015-07-27 17:42:39 -070034 finally:
Scott Bakere08b4562015-08-11 17:23:52 -070035 if tmp_pathname:
36 os.remove(tmp_pathname)
37
38 self.log_to_console = log_to_console
39 self.log_msgs = []
Scott Baker66566722015-07-27 17:42:39 -070040
Scott Baker9fdffff2015-08-04 23:52:18 -070041 self.compute_dependencies()
42
Scott Baker404c46d2015-08-24 15:50:03 -070043 self.deferred_sync = []
44
Scott Baker9fdffff2015-08-04 23:52:18 -070045 self.ordered_nodetemplates = []
46 self.ordered_names = self.topsort_dependencies()
Scott Baker9d178862015-09-03 14:32:48 -070047 self.log("ordered_names: %s" % self.ordered_names)
Scott Baker9fdffff2015-08-04 23:52:18 -070048 for name in self.ordered_names:
49 if name in self.nodetemplates_by_name:
50 self.ordered_nodetemplates.append(self.nodetemplates_by_name[name])
51
Scott Baker66566722015-07-27 17:42:39 -070052 #pdb.set_trace()
53
Scott Bakere08b4562015-08-11 17:23:52 -070054 def log(self, msg):
55 if self.log_to_console:
56 print msg
57 self.log_msgs.append(msg)
58
Scott Baker9fdffff2015-08-04 23:52:18 -070059 def compute_dependencies(self):
60 nodetemplates_by_name = {}
Scott Baker66566722015-07-27 17:42:39 -070061 for nodetemplate in self.template.nodetemplates:
Scott Baker9fdffff2015-08-04 23:52:18 -070062 nodetemplates_by_name[nodetemplate.name] = nodetemplate
63
64 self.nodetemplates_by_name = nodetemplates_by_name
65
66 for nodetemplate in self.template.nodetemplates:
67 nodetemplate.dependencies = []
68 nodetemplate.dependencies_names = []
69 for reqs in nodetemplate.requirements:
70 for (k,v) in reqs.items():
71 name = v["node"]
72 if (name in nodetemplates_by_name):
73 nodetemplate.dependencies.append(nodetemplates_by_name[name])
74 nodetemplate.dependencies_names.append(name)
75
Scott Bakerf828c3e2015-08-05 18:23:14 -070076 # go another level deep, as our requirements can have requirements...
77 for sd_req in v.get("requirements",[]):
78 for (sd_req_k, sd_req_v) in sd_req.items():
79 name = sd_req_v["node"]
80 if (name in nodetemplates_by_name):
81 nodetemplate.dependencies.append(nodetemplates_by_name[name])
82 nodetemplate.dependencies_names.append(name)
83
84
Scott Baker9fdffff2015-08-04 23:52:18 -070085 def topsort_dependencies(self):
86 # stolen from observer
87 g = self.nodetemplates_by_name
88
89 # Get set of all nodes, including those without outgoing edges
90 keys = set(g.keys())
91 values = set({})
92 for v in g.values():
93 values=values | set(v.dependencies_names)
94
95 all_nodes=list(keys|values)
96 steps = all_nodes
97
98 # Final order
99 order = []
100
101 # DFS stack, not using recursion
102 stack = []
103
104 # Unmarked set
105 unmarked = all_nodes
106
107 # visiting = [] - skip, don't expect 1000s of nodes, |E|/|V| is small
108
109 while unmarked:
110 stack.insert(0,unmarked[0]) # push first unmarked
111
112 while (stack):
113 n = stack[0]
114 add = True
115 try:
116 for m in g[n].dependencies_names:
117 if (m in unmarked):
118 add = False
119 stack.insert(0,m)
120 except KeyError:
121 pass
122 if (add):
123 if (n in steps and n not in order):
124 order.append(n)
125 item = stack.pop(0)
126 try:
127 unmarked.remove(item)
128 except ValueError:
129 pass
130
131 noorder = list(set(steps) - set(order))
132 return order + noorder
133
134 def execute(self, user):
Scott Baker13399c02015-08-05 16:35:09 -0700135 for nodetemplate in self.ordered_nodetemplates:
Scott Baker66566722015-07-27 17:42:39 -0700136 self.execute_nodetemplate(user, nodetemplate)
137
Scott Baker404c46d2015-08-24 15:50:03 -0700138 for obj in self.deferred_sync:
139 self.log("Saving deferred sync obj %s" % obj)
140 obj.no_sync = False
141 obj.save()
142
Scott Baker66566722015-07-27 17:42:39 -0700143 def execute_nodetemplate(self, user, nodetemplate):
Scott Baker3841b372015-08-03 14:20:31 -0700144 if nodetemplate.type in resources.resources:
145 cls = resources.resources[nodetemplate.type]
Scott Bakerc4005d02015-08-06 17:21:34 -0700146 #print "work on", cls.__name__, nodetemplate.name
Scott Baker5d432142015-08-07 17:06:47 -0700147 obj = cls(user, nodetemplate, self)
Scott Baker9fdb39f2015-08-04 16:44:18 -0700148 obj.create_or_update()
Scott Baker404c46d2015-08-24 15:50:03 -0700149 self.deferred_sync = self.deferred_sync + obj.deferred_sync
Scott Baker7e472dd2015-07-31 12:30:28 -0700150
Scott Baker8899be92015-08-04 17:02:29 -0700151 def destroy(self, user):
Scott Baker9fdffff2015-08-04 23:52:18 -0700152 nodetemplates = self.ordered_nodetemplates
Scott Baker8899be92015-08-04 17:02:29 -0700153 models = []
Scott Baker9fdffff2015-08-04 23:52:18 -0700154 for nodetemplate in nodetemplates:
Scott Baker8899be92015-08-04 17:02:29 -0700155 if nodetemplate.type in resources.resources:
156 cls = resources.resources[nodetemplate.type]
Scott Baker5d432142015-08-07 17:06:47 -0700157 obj = cls(user, nodetemplate, self)
Scott Baker13399c02015-08-05 16:35:09 -0700158 for model in obj.get_existing_objs():
159 models.append( (obj, model) )
Scott Baker8899be92015-08-04 17:02:29 -0700160 models.reverse()
Scott Baker13399c02015-08-05 16:35:09 -0700161 for (resource,model) in models:
Scott Baker13399c02015-08-05 16:35:09 -0700162 resource.delete(model)
Scott Baker66566722015-07-27 17:42:39 -0700163
Scott Baker5d432142015-08-07 17:06:47 -0700164 def name_to_xos_class(self, user, name):
165 nt = self.nodetemplates_by_name.get(name)
166 if not nt:
167 raise Exception("failed to find nodetemplate %s" % name)
168
169 cls = resources.resources.get(nt.type)
170 if not cls:
171 raise Exception("nodetemplate %s's type does not resolve to a known resource type" % name)
172
173 return (nt, cls, cls.xos_model)
174
175 def name_to_xos_model(self, user, name):
176 (nt, cls, model_class) = self.name_to_xos_class(user, name)
177 obj = cls(user, nt, self)
178 existing_objs = obj.get_existing_objs()
179 if not existing_objs:
180 raise Exception("failed to find xos %s %s" % (cls.__name__, name))
181 return existing_objs[0]
182