+#!/usr/bin/python
+import os
+import datetime
+
+from PLC.Config import Config
+from PLC.Interfaces import Interface, Interfaces
+from PLC.InterfaceTags import InterfaceTag, InterfaceTags
+from PLC.Keys import Key, Keys
+
+# For PLC 4.3
+try:
+ from PLC.Methods.GetSliceFamily import GetSliceFamily
+except ImportError:
+ pass
+
+from PLC.NodeGroups import NodeGroup, NodeGroups
+from PLC.NodeTags import NodeTag, NodeTags
+from PLC.Nodes import Node, Nodes
+from PLC.Persons import Person, Persons
+from PLC.SliceTags import SliceTag, SliceTags
+from PLC.Slices import Slice, Slices
+from PLC.TagTypes import TagTypes
+
+from pyaspects.meta import MetaAspect
+
+import func.overlord.client
+
+def absorb_exception(function_name):
+ def _wrapper(*args, **kwargs):
+ try:
+ return function_name(*args, **kwargs)
+ except:
+ return None
+ return _wrapper
+
+
+class BaseFunc(object):
+
+ def __init__(self):
+ self.log = open("/var/log/funcaspect/plc_slice_calls.log", "a")
+ #self.log = None
+
+ self.interface_id = None
+ self.node_ids = None
+ self.person = None
+ self.person_name_or_id = None
+ self.slice = None
+ self.slice_ids = None
+ self.slice_name_or_id = None
+ self.tag = None
+ self.tag_name_or_id = None
+ self.tag_value = None
+
+ def logit(self, call, args, kwargs, data, slice):
+ if not self.log: return
+
+ self.log.write("%s : args: %s kwargs: %s\n" % (call, args, kwargs))
+ self.log.write("data: %s\n" % data)
+ self.log.write("%s\n\n" % slice)
+ self.log.flush()
+
+ @absorb_exception
+ def get_slice(self, api, slice_id_or_name):
+ slice_filter = {}
+ try: # if integer
+ slice_filter["slice_id"] = int(str(slice_id_or_name))
+ except ValueError:
+ # we have a string
+ slice_filter["name"] = slice_id_or_name
+ slice = Slices(api, slice_filter = slice_filter)[0]
+ return slice
+
+ @absorb_exception
+ def get_node_tag(self, api, node_id_or_name):
+ tag_filter = {}
+ try: # if integer
+ tag_filter["node_tag_id"] = int(str(node_id_or_name))
+ except ValueError:
+ # we have a string
+ tag_filter["tagname"] = node_id_or_name
+ tag = NodeTags(api, node_tag_filter = tag_filter)[0]
+ return tag
+
+ @absorb_exception
+ def get_person(self, api, person_id_or_name):
+ person_filter = {}
+ try: # if integer
+ person_filter["person_id"] = int(str(person_id_or_name))
+ except ValueError:
+ # we have a string
+ person_filter["email"] = person_id_or_name
+ person = Persons(api, person_filter = person_filter)[0]
+ return person
+
+ @absorb_exception
+ def get_interface(self, api, interface_id):
+ return Interfaces(api, interface_filter = {"interface_id": interface_id})
+
+ @absorb_exception
+ def get_interfaces(self, api, node_id):
+ return Interfaces(api, interface_filter = {"node_id": node_id})
+
+ @absorb_exception
+ def get_slice_family(self, api, slice_id_or_name):
+ # For PLC 4.3
+ try:
+ return GetSliceFamily(api).call(api, slice_id_or_name)
+ except NameError:
+ return "planetlab-f8-i386"
+
+ @absorb_exception
+ def get_slice_tag(self, api, tag_id_or_name):
+ tag_filter = {}
+ try: # if integer
+ tag_filter["slice_tag_id"] = int(str(tag_id_or_name))
+ except ValueError:
+ # we have a string
+ tag_filter["tagname"] = tag_id_or_name
+ tag = SliceTags(api, slice_tag_filter = tag_filter)[0]
+ return tag
+
+ @absorb_exception
+ def get_tag_type(self, api, type_id_or_name):
+ tag_filter = {}
+ try: # if integer
+ tag_filter["tag_type_id"] = int(str(type_id_or_name))
+ except ValueError:
+ # we have a string
+ tag_filter["tagname"] = type_id_or_name
+ tag = TagTypes(api, tag_type_filter = tag_filter)[0]
+ return tag
+
+ @absorb_exception
+ def get_node_hostname(self, api, node_id_or_hostname):
+ node_filter = {}
+ try: # if integer
+ node_filter["node_id"] = int(str(node_id_or_hostname))
+ except ValueError:
+ # we have a string
+ node_filter["hostname"] = node_id_or_hostname
+ node = Nodes(api, node_filter = node_filter)[0]
+ return node["hostname"]
+
+ @absorb_exception
+ def get_slice_tags(self, api, slice_id):
+ return SliceTags(api, slice_tag_filter = {"slice_id": slice_id})
+
+ @absorb_exception
+ def get_slice_tags_with_tag_type(self, api, tag_type_id):
+ return SliceTags(api, slice_tag_filter = {"tag_type_id": tag_type_id})
+
+ @absorb_exception
+ def get_person_keys(self, api, person_ids):
+ return Keys(api, key_filter = {"person_id": person_ids})
+
+ @absorb_exception
+ def get_node_tags(self, api, node_id):
+ return NodeTags(api, node_tag_filter = {"node_id": node_id})
+
+ @absorb_exception
+ def get_interface_tags(self, api, interface_id):
+ return InterfaceTags(api, interface_tag_filter = {"interface_id": interface_id})
+
+ @absorb_exception
+ def get_node_groups(self, api, nodegroup_id):
+ return NodeGroups(api, nodegroup_filter = {"nodegroup_id": nodegroup_id})
+
+ def add_slice_to_node(self, slice, node, family, tags, keys):
+ pass
+
+ def delete_slice_from_node(self, slice, node):
+ pass
+
+ def add_person_to_slice(self, slice, node, person, value):
+ pass
+
+ def delete_person_from_slice(self, slice, node, person, value):
+ pass
+
+ def add_slice_tag(self, slice, node, tag, value):
+ pass
+
+ def add_node_tag(self, node, tag, value):
+ pass
+
+ def add_interface(self, node, value):
+ pass
+
+ def delete_interface(self, node, value):
+ pass
+
+ def delete_node_tag(self, node, tag, value):
+ pass
+
+ def delete_slice_tag(self, slice, node, tag, value):
+ pass
+
+ def update_node_tag(self, node, tag, value):
+ pass
+
+ def update_slice_tag(self, slice, node, tag, value):
+ pass
+
+ # aspect method which assigns the required variables
+ def before(self, wobj, data, *args, **kwargs):
+ api_method_name = wobj.name
+
+ if api_method_name == "AddSliceToNodes" or api_method_name == "DeleteSliceFromNodes":
+ self.slice_name_or_id = args[1]
+ self.node_ids = args[2]
+ elif api_method_name == "AddPersonToSlice" or api_method_name == "DeletePersonFromSlice":
+ self.person_name_or_id = args[1]
+ self.slice_name_or_id = args[2]
+
+ elif api_method_name == "AddSliceTag":
+ self.slice_name_or_id = args[1]
+ self.tag_name_or_id = args[2]
+ self.tag_value = args[3]
+ elif api_method_name == "DeleteSliceTag":
+ self.tag_name_or_id = args[1]
+ # keep it in memory
+ self.tag = self.get_slice_tag(wobj.api, self.tag_name_or_id)
+ self.slice = self.get_slice(wobj.api, self.tag["slice_id"])
+
+ elif api_method_name == "AddNodeTag":
+ self.node_ids = [args[1]]
+ self.tag_name_or_id = args[2]
+ self.tag_value = args[3]
+ elif api_method_name == "DeleteNodeTag":
+ self.tag_name_or_id = args[1]
+ # keep it in memory
+ self.tag = self.get_node_tag(wobj.api, self.tag_name_or_id)
+ elif api_method_name == "UpdateSliceTag" or api_method_name == "UpdateNodeTag":
+ self.tag_name_or_id = args[1]
+ self.tag_value = args[2]
+
+ elif api_method_name == "AddInterface" or api_method_name == "UpdateInterface":
+ self.node_ids = [args[1]]
+ elif api_method_name == "DeleteInterface":
+ self.interface_id = args[1]
+
+ elif api_method_name == "DeleteSlice":
+ self.slice_name_or_id = args[1]
+ elif api_method_name == "DeletePerson":
+ self.person_name_or_id = args[1]
+ # keep it in memory
+ self.person = self.get_person(wobj.api, self.person_name_or_id)
+ elif api_method_name == "DeleteTagType":
+ self.tag_name_or_id = args[1]
+ # keep it in memory
+ tag_type = self.get_tag_type(wobj.api, self.tag_name_or_id)[0]["tag_type_id"]
+ self.slice_ids = [slice_ids["slice_id"] for slice_ids in self.get_slice_tags_with_tag_type(wobj.api, tag_type)]
+ self.slice_ids = list(set(self.slice_ids))
+ # Node/NodeGroups ???
+ #GetNodeTags
+ #GetInterfaceTags
+ else: # ignore the rest
+ return
+
+ if self.slice_name_or_id != None:
+ self.slice = self.get_slice(wobj.api, self.slice_name_or_id)
+
+# self.logit(wobj.name, args, kwargs, data, slice)
+
+ # aspect method
+ def after(self, wobj, data, *args, **kwargs):
+ #if data.has_key("method_return_value") and data['method_return_value'] > 0:
+ # # return value 1 means that API call was successful, we can go on.
+ # pass
+ #else:
+ # return
+
+ api_method_name = wobj.name
+
+ # assign globals to locals
+ interface_id = self.interface_id
+ node_ids = self.node_ids
+ person_name_or_id = self.person_name_or_id
+ slice = self.slice
+ tag = self.tag
+ person = self.person
+ tag_name_or_id = self.tag_name_or_id
+ tag_value = self.tag_value
+
+ if api_method_name == "AddSliceToNodes":
+ slice_tags = self.get_slice_tags(wobj.api, slice["slice_id"])
+ slice_keys = self.get_person_keys(wobj.api, slice["person_ids"])
+ slice_family = self.get_slice_family(wobj.api, slice["slice_id"])
+ for node_id in node_ids:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.add_slice_to_node(slice["name"], node_hostname, slice_family, slice_tags, slice_keys)
+ elif api_method_name == "DeleteSliceFromNodes":
+ for node_id in node_ids:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.delete_slice_from_node(slice["name"], node_hostname)
+
+ elif api_method_name == "AddPersonToSlice":
+ person = self.get_person(wobj.api, person_name_or_id)
+ keys = self.get_person_keys(wobj.api, slice["person_ids"])
+ keys += self.get_person_keys(wobj.api, person["person_id"])
+ for node_id in slice["node_ids"]:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.add_person_to_slice(slice["name"], node_hostname, person["email"], keys)
+ elif api_method_name == "DeletePersonFromSlice":
+ person = self.get_person(wobj.api, person_name_or_id)
+ keys = self.get_person_keys(wobj.api, slice["person_ids"])
+ keys.remove(self.get_person_keys(wobj.api, slice["person_ids"])[0])
+ for node_id in slice["node_ids"]:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.delete_person_from_slice(slice["name"], node_hostname, person["email"], keys)
+
+ elif api_method_name == "AddSliceTag":
+ tag = self.get_tag_type(wobj.api, tag_name_or_id)
+
+ if len(args) == 4:
+ node_ids = slice["node_ids"]
+ elif len(args) == 5:
+ node_ids = [args[4]]
+ else:
+ node_groups = self.get_node_groups(wobj.api, args[5])
+ node_ids = set.intersection(set(node_groups[0]["node_ids"]), set(slice["node_ids"]))
+
+ for node_id in node_ids:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.add_slice_tag(slice["name"], node_hostname, tag["tagname"], tag_value)
+ elif api_method_name == "DeleteSliceTag":
+ slice = self.get_slice(wobj.api, tag["slice_id"])
+ for node_id in slice["node_ids"]:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.delete_slice_tag(slice["name"], node_hostname, tag["tagname"], tag["value"])
+ elif api_method_name == "UpdateSliceTag":
+ tag = self.get_slice_tag(wobj.api, tag_name_or_id)
+ slice = self.get_slice(wobj.api, tag["slice_id"])
+ for node_id in slice["node_ids"]:
+ node_hostname = self.get_node_hostname(wobj.api, tag["node_id"])
+ self.update_slice_tag(slice, node_hostname, tag["tagname"], tag_value)
+
+ elif api_method_name == "AddNodeTag":
+ tag = self.get_tag_type(wobj.api, tag_name_or_id)
+ for node_id in node_ids:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.add_node_tag(node_hostname, tag["tagname"], tag_value)
+ elif api_method_name == "DeleteNodeTag":
+ node_hostname = self.get_node_hostname(wobj.api, tag["node_id"])
+ self.delete_node_tag(node_hostname, tag["tagname"], tag["value"])
+ elif api_method_name == "UpdateNodeTag":
+ tag = self.get_node_tag(wobj.api, tag_name_or_id)
+ for node_id in [tag["node_id"]]:
+ node_hostname = self.get_node_hostname(wobj.api, tag["node_id"])
+ self.update_node_tag(node_hostname, tag["tagname"], tag_value)
+
+ elif api_method_name == "AddInterface" or api_method_name == "UpdateInterface":
+ for node_id in node_ids:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ node_interfaces = self.get_interfaces(wobj.api, node_id)
+ for node_interface in node_interfaces:
+ #FIXME: Requires pyplnet changes
+ interface_tags = self.get_interface_tags(wobj.api, node_interface["interface_tag_ids"])
+ node_interface["interface_tags"] = interface_tags
+ self.add_interface(node_hostname, node_interfaces)
+# elif api_method_name == "DeleteInterface":
+# node_interface = self.get_interface(wobj.api, interface_id)
+# for node_id in node_interface["node_id"]:
+# node_hostname = self.get_node_hostname(wobj.api, node_id)
+# node_interfaces = self.get_interfaces(wobj.api, node_id)
+# for node_interface in node_interfaces:
+# #FIXME: Requires pyplnet changes
+# interface_tags = self.get_interface_tags(wobj.api, node_interface["interface_tag_ids"])
+# node_interface["interface_tags"] = interface_tags
+# self.delete_interface(node_hostname, node_interfaces)
+
+ elif api_method_name == "DeleteSlice":
+ for node_id in slice["node_ids"]:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.delete_slice_from_node(slice["name"], node_hostname)
+ elif api_method_name == "DeletePerson":
+ #FIXME: Role
+ slice_ids = person["slice_ids"]
+ for slice_id in slice_ids:
+ slice = self.get_slice(wobj.api, slice_id)
+ keys = self.get_person_keys(wobj.api, slice["person_ids"])
+ for node_id in slice["node_ids"]:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.delete_person_from_slice(slice["name"], node_hostname, person["email"], keys)
+ elif api_method_name == "DeleteTagType":
+ #FIXME: NodeGroups etc.
+ for slice in self.slice_ids:
+ slice = self.get_slice(wobj.api, tag["slice_id"])
+ for node_id in slice["node_ids"]:
+ node_hostname = self.get_node_hostname(wobj.api, node_id)
+ self.delete_slice_tag(slice["name"], node_hostname, tag["tagname"], tag["value"])
+
+# self.logit(wobj.name, args, kwargs, data, slice)
+
+class FuncAspect_class(BaseFunc):
+ __metaclass__ = MetaAspect
+ name = "funcaspect_class"
+
+ #node_list = func.overlord.client.Client("*").list_minions()
+ #FIXME: Only control following nodes
+ node_list = ["planetlab-01.cs.princeton.edu", "planetlab-02.cs.princeton.edu", "planetlab-04.cs.princeton.edu", "planetlab-05.cs.princeton.edu"]
+
+ client = None
+
+ def __init__(self):
+ BaseFunc.__init__(self)
+
+ def write_to_log(self, line):
+ if not self.log: return
+
+ date = datetime.datetime.now().strftime("%d/%m/%y %H:%M")
+ self.log.write("%s - %s" % (date, line))
+ self.log.flush()
+
+ def ping(self, node):
+ try:
+ self.client = func.overlord.client.Client(node, timeout = 10)
+ except:
+ self.client = None
+ return False
+
+ if self.client.test.ping()[node]:
+ self.client = func.overlord.client.Client(node, timeout = 10, async = True)
+ return True
+
+ self.client = None
+ return False
+
+ def add_slice_to_node(self, slice, node, family, tags, keys):
+ self.write_to_log("Func: AddSlice: %s toNode: %s Family: %s\n" % (slice, node, family))
+
+ if node in self.node_list:
+ self.increment_revision_for_node(node)
+ if self.ping(node):
+ self.client.nm.AddSliceToNode(slice, tags, keys)
+ else:
+ self.write_to_log("Func: (AddSlice)Cannot access to node: %s" % node)
+
+# if self.ping(node):
+# self.client.nm.AddSliceToNode(slice, interfaces, family, tags, keys)
+# else:
+# AddToQueue
+
+ def delete_slice_from_node(self, slice, node):
+ self.write_to_log("Func: DeleteSlice: %s FromNode: %s\n" % (slice, node))
+
+ if node in self.node_list:
+ self.increment_revision_for_node(node)
+ if self.ping(node):
+ self.client.nm.DeleteSliceFromNode(slice)
+ else:
+ self.write_to_log("Func: (DeleteSlice)Cannot access to node: %s" % node)
+
+# if self.pingnode(node):
+# self.client.nm.DeleteSliceFromNode(slice)
+# else:
+# AddToQueue
+
+ def add_person_to_slice(self, slice, node, person, value):
+ self.write_to_log("Func: AddPerson: %s ToSlice: %s onNode: %s\n" % (person, slice, node))
+
+ if node in self.node_list:
+ self.increment_revision_for_node(node)
+ if self.ping(node):
+ self.client.nm.AddPersonToSlice(slice, value)
+ else:
+ self.write_to_log("Func: (AddPersonToSlice)Cannot access to node: %s" % node)
+
+# if self.ping(node):
+# self.client.nm.AddPersonToSlice(slice, value)
+# else:
+# AddToQueue
+
+ def delete_person_from_slice(self, slice, node, person, value):
+ self.write_to_log("Func: DeletePerson: %s FromSlice: %s onNode: %s\n" % (person, slice, node))
+
+ if node in self.node_list:
+ self.increment_revision_for_node(node)
+ if self.ping(node):
+ self.client.nm.DeletePersonFromSlice(slice, value)
+ else:
+ self.write_to_log("Func: (DeletePersonFromSlice)Cannot access to node: %s" % node)
+
+# if self.ping(node):
+# self.client.nm.DeletePersonFromSlice(slice, value)
+# else:
+# AddToQueue
+
+ def add_slice_tag(self, slice, node, tag, value):
+ self.write_to_log("Func: AddSliceTag: %s Value: %s onSlice:%s onNode: %s\n" % (tag, value, slice, node))
+
+ if node in self.node_list:
+ self.increment_revision_for_node(node)
+ if self.ping(node):
+ self.client.nm.AddSliceTag(slice, tag, value)
+ else:
+ self.write_to_log("Func: (AddSliceTag)Cannot access to node: %s" % node)
+
+# if self.ping(node):
+# self.client.nm.AddSliceTag(slice, tag, value)
+# else:
+# AddToQueue
+
+ def delete_slice_tag(self, slice, node, tag, value):
+ self.write_to_log("Func: DeleteSliceTag: %s Value: %s onSlice:%s onNode: %s\n" % (tag, value, slice, node))
+
+ if node in self.node_list:
+ self.increment_revision_for_node(node)
+ if self.ping(node):
+ self.client.nm.DeleteSliceTag(slice, tag, value)
+ else:
+ self.write_to_log("Func: (DeleteSliceTag)Cannot access to node: %s" % node)
+
+# if self.ping(node):
+# self.client.nm.DeleteSliceTag(slice, tag, value)
+# else:
+# AddToQueue
+
+ def update_slice_tag(self, slice, node, tag, value):
+ self.write_to_log("Func: UpdateSliceTag: %s Value: %s toSlice: %s onNode: %s\n" % (tag, value, slice, node))
+
+# client = func.overlord.client.Client(node, timeout=5, async=True)
+# if self.ping(node):
+# self.client.nm.UpdateSliceTag(slice, tag, value)
+# else:
+# AddToQueue
+
+ def add_node_tag(self, node, tag, value):
+ self.write_to_log("Func: AddNodeTag: %s Value: %s toNode: %s\n" % (tag, value, node))
+
+# if self.ping(node):
+# self.client.nm.AddNodeTag(tag, value)
+# else:
+# AddToQueue
+
+ def delete_node_tag(self, node, tag, value):
+ self.write_to_log("Func: DeleteNodeTag: %s Value: %s fromNode: %s\n" % (tag, value, node))
+
+# if self.ping(node):
+# self.client.nm.DeleteSliceTag(tag, value)
+# else:
+# AddToQueue
+
+ def update_node_tag(self, node, tag, value):
+ self.write_to_log("Func: UpdateNodeTag: %s Value: %s toNode: %s\n" % (tag, value, node))
+
+# if self.ping(node):
+# self.client.nm.UpdateNodeTag(tag, value)
+# else:
+# AddToQueue
+
+ def add_interface(self, node, value):
+ self.write_to_log("Func: AddInterface: %s toNode: %s\n" % (len(value), node))
+
+# if self.ping(node):
+# self.client.nm.AddInterface(value)
+# else:
+# AddToQueue
+
+ def delete_interface(self, node, value):
+ self.write_to_log("Func: DeleteInterface: %s toNode: %s\n" % (len(value), node))
+
+# if self.ping(node):
+# self.client.nm.DeleteInterface(value)
+# else:
+# AddToQueue
+
+ @absorb_exception
+ def increment_revision_for_node(self, node):
+ filename = "/var/www/html/func/%s" % node
+ value = 0
+
+ if os.path.exists(filename):
+ f = open(filename, "r")
+ value = int(f.read().strip())
+ f.close()
+
+ f = open(filename, "w")
+ value += 1
+ f.write("%d" % int(value))
+ f.close()
+
+ def before(self, wobj, data, *args, **kwargs):
+ BaseFunc.before(self, wobj, data, *args, **kwargs)
+
+ def after(self, wobj, data, *args, **kwargs):
+ BaseFunc.after(self, wobj, data, *args, **kwargs)
+
+FuncAspect = FuncAspect_class