+ return None
+
+ # Service Function Instances
+ def new_sfi(self, task):
+ vim_sfi_id = None
+ try:
+ # Waits for interfaces to be ready (avoids failure)
+ time.sleep(1)
+ dep_id = "TASK-" + str(task["extra"]["depends_on"][0])
+ task_id = task["instance_action_id"] + "." + str(task["task_index"])
+ error_text = ""
+ interfaces = task["depends"][dep_id]["extra"].get("interfaces")
+
+ ingress_interface_id = task.get("extra").get("params").get("ingress_interface_id")
+ egress_interface_id = task.get("extra").get("params").get("egress_interface_id")
+ ingress_vim_interface_id = None
+ egress_vim_interface_id = None
+ for vim_interface, interface_data in interfaces.iteritems():
+ if interface_data.get("interface_id") == ingress_interface_id:
+ ingress_vim_interface_id = vim_interface
+ break
+ if ingress_interface_id != egress_interface_id:
+ for vim_interface, interface_data in interfaces.iteritems():
+ if interface_data.get("interface_id") == egress_interface_id:
+ egress_vim_interface_id = vim_interface
+ break
+ else:
+ egress_vim_interface_id = ingress_vim_interface_id
+ if not ingress_vim_interface_id or not egress_vim_interface_id:
+ error_text = "Error creating Service Function Instance, Ingress: {}, Egress: {}".format(
+ ingress_vim_interface_id, egress_vim_interface_id)
+ self.logger.error(error_text)
+ task["error_msg"] = error_text
+ task["status"] = "FAILED"
+ task["vim_id"] = None
+ return None
+ # At the moment, every port associated with the VM will be used both as ingress and egress ports.
+ # Bear in mind that different VIM connectors might support SFI differently. In the case of OpenStack,
+ # only the first ingress and first egress ports will be used to create the SFI (Port Pair).
+ ingress_port_id_list = [ingress_vim_interface_id]
+ egress_port_id_list = [egress_vim_interface_id]
+ name = "sfi-%s" % task["item_id"][:8]
+ # By default no form of IETF SFC Encapsulation will be used
+ vim_sfi_id = self.vim.new_sfi(name, ingress_port_id_list, egress_port_id_list, sfc_encap=False)
+
+ task["extra"]["created"] = True
+ task["extra"]["vim_status"] = "ACTIVE"
+ task["error_msg"] = None
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ task["vim_id"] = vim_sfi_id
+ instance_element_update = {"status": "ACTIVE", "vim_sfi_id": vim_sfi_id, "error_msg": None}
+ return instance_element_update
+
+ except (vimconn.vimconnException, VimThreadException) as e:
+ self.logger.error("Error creating Service Function Instance, task=%s: %s", task_id, str(e))
+ error_text = self._format_vim_error_msg(str(e))
+ task["error_msg"] = error_text
+ task["status"] = "FAILED"
+ task["vim_id"] = None
+ instance_element_update = {"status": "VIM_ERROR", "vim_sfi_id": None, "error_msg": error_text}
+ return instance_element_update
+
+ def del_sfi(self, task):
+ sfi_vim_id = task["vim_id"]
+ try:
+ self.vim.delete_sfi(sfi_vim_id)
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ task["error_msg"] = None
+ return None
+
+ except vimconn.vimconnException as e:
+ task["error_msg"] = self._format_vim_error_msg(str(e))
+ if isinstance(e, vimconn.vimconnNotFoundException):
+ # If not found mark as Done and fill error_msg
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ return None
+ task["status"] = "FAILED"
+ return None
+
+ def new_sf(self, task):
+ vim_sf_id = None
+ try:
+ task_id = task["instance_action_id"] + "." + str(task["task_index"])
+ error_text = ""
+ depending_tasks = ["TASK-" + str(dep_id) for dep_id in task["extra"]["depends_on"]]
+ # sfis = task.get("depends").values()[0].get("extra").get("params")[5]
+ sfis = [task.get("depends").get(dep_task) for dep_task in depending_tasks]
+ sfi_id_list = []
+ for sfi in sfis:
+ sfi_id_list.append(sfi.get("vim_id"))
+ name = "sf-%s" % task["item_id"][:8]
+ # By default no form of IETF SFC Encapsulation will be used
+ vim_sf_id = self.vim.new_sf(name, sfi_id_list, sfc_encap=False)
+
+ task["extra"]["created"] = True
+ task["extra"]["vim_status"] = "ACTIVE"
+ task["error_msg"] = None
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ task["vim_id"] = vim_sf_id
+ instance_element_update = {"status": "ACTIVE", "vim_sf_id": vim_sf_id, "error_msg": None}
+ return instance_element_update
+
+ except (vimconn.vimconnException, VimThreadException) as e:
+ self.logger.error("Error creating Service Function, task=%s: %s", task_id, str(e))
+ error_text = self._format_vim_error_msg(str(e))
+ task["error_msg"] = error_text
+ task["status"] = "FAILED"
+ task["vim_id"] = None
+ instance_element_update = {"status": "VIM_ERROR", "vim_sf_id": None, "error_msg": error_text}
+ return instance_element_update
+
+ def del_sf(self, task):
+ sf_vim_id = task["vim_id"]
+ try:
+ self.vim.delete_sf(sf_vim_id)
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ task["error_msg"] = None
+ return None
+
+ except vimconn.vimconnException as e:
+ task["error_msg"] = self._format_vim_error_msg(str(e))
+ if isinstance(e, vimconn.vimconnNotFoundException):
+ # If not found mark as Done and fill error_msg
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ return None
+ task["status"] = "FAILED"
+ return None
+
+ def new_classification(self, task):
+ vim_classification_id = None
+ try:
+ params = task["params"]
+ task_id = task["instance_action_id"] + "." + str(task["task_index"])
+ dep_id = "TASK-" + str(task["extra"]["depends_on"][0])
+ error_text = ""
+ interfaces = task.get("depends").get(dep_id).get("extra").get("interfaces").keys()
+ # Bear in mind that different VIM connectors might support Classifications differently.
+ # In the case of OpenStack, only the first VNF attached to the classifier will be used
+ # to create the Classification(s) (the "logical source port" of the "Flow Classifier").
+ # Since the VNFFG classifier match lacks the ethertype, classification defaults to
+ # using the IPv4 flow classifier.
+ name = "c-%s" % task["item_id"][:8]
+ # if not CIDR is given for the IP addresses, add /32:
+ ip_proto = int(params.get("ip_proto"))
+ source_ip = params.get("source_ip")
+ destination_ip = params.get("destination_ip")
+ source_port = params.get("source_port")
+ destination_port = params.get("destination_port")
+ definition = {"logical_source_port": interfaces[0]}
+ if ip_proto:
+ if ip_proto == 1:
+ ip_proto = 'icmp'
+ elif ip_proto == 6:
+ ip_proto = 'tcp'
+ elif ip_proto == 17:
+ ip_proto = 'udp'
+ definition["protocol"] = ip_proto
+ if source_ip:
+ if '/' not in source_ip:
+ source_ip += '/32'
+ definition["source_ip_prefix"] = source_ip
+ if source_port:
+ definition["source_port_range_min"] = source_port
+ definition["source_port_range_max"] = source_port
+ if destination_port:
+ definition["destination_port_range_min"] = destination_port
+ definition["destination_port_range_max"] = destination_port
+ if destination_ip:
+ if '/' not in destination_ip:
+ destination_ip += '/32'
+ definition["destination_ip_prefix"] = destination_ip
+
+ vim_classification_id = self.vim.new_classification(
+ name, 'legacy_flow_classifier', definition)
+
+ task["extra"]["created"] = True
+ task["extra"]["vim_status"] = "ACTIVE"
+ task["error_msg"] = None
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ task["vim_id"] = vim_classification_id
+ instance_element_update = {"status": "ACTIVE", "vim_classification_id": vim_classification_id,
+ "error_msg": None}
+ return instance_element_update
+
+ except (vimconn.vimconnException, VimThreadException) as e:
+ self.logger.error("Error creating Classification, task=%s: %s", task_id, str(e))
+ error_text = self._format_vim_error_msg(str(e))
+ task["error_msg"] = error_text
+ task["status"] = "FAILED"
+ task["vim_id"] = None
+ instance_element_update = {"status": "VIM_ERROR", "vim_classification_id": None, "error_msg": error_text}
+ return instance_element_update
+
+ def del_classification(self, task):
+ classification_vim_id = task["vim_id"]
+ try:
+ self.vim.delete_classification(classification_vim_id)
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ task["error_msg"] = None
+ return None
+
+ except vimconn.vimconnException as e:
+ task["error_msg"] = self._format_vim_error_msg(str(e))
+ if isinstance(e, vimconn.vimconnNotFoundException):
+ # If not found mark as Done and fill error_msg
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ return None
+ task["status"] = "FAILED"
+ return None
+
+ def new_sfp(self, task):
+ vim_sfp_id = None
+ try:
+ task_id = task["instance_action_id"] + "." + str(task["task_index"])
+ depending_tasks = [task.get("depends").get("TASK-" + str(tsk_id)) for tsk_id in
+ task.get("extra").get("depends_on")]
+ error_text = ""
+ sf_id_list = []
+ classification_id_list = []
+ for dep in depending_tasks:
+ vim_id = dep.get("vim_id")
+ resource = dep.get("item")
+ if resource == "instance_sfs":
+ sf_id_list.append(vim_id)
+ elif resource == "instance_classifications":
+ classification_id_list.append(vim_id)
+
+ name = "sfp-%s" % task["item_id"][:8]
+ # By default no form of IETF SFC Encapsulation will be used
+ vim_sfp_id = self.vim.new_sfp(name, classification_id_list, sf_id_list, sfc_encap=False)
+
+ task["extra"]["created"] = True
+ task["extra"]["vim_status"] = "ACTIVE"
+ task["error_msg"] = None
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ task["vim_id"] = vim_sfp_id
+ instance_element_update = {"status": "ACTIVE", "vim_sfp_id": vim_sfp_id, "error_msg": None}
+ return instance_element_update
+
+ except (vimconn.vimconnException, VimThreadException) as e:
+ self.logger.error("Error creating Service Function, task=%s: %s", task_id, str(e))
+ error_text = self._format_vim_error_msg(str(e))
+ task["error_msg"] = error_text
+ task["status"] = "FAILED"
+ task["vim_id"] = None
+ instance_element_update = {"status": "VIM_ERROR", "vim_sfp_id": None, "error_msg": error_text}
+ return instance_element_update
+
+ def del_sfp(self, task):
+ sfp_vim_id = task["vim_id"]
+ try:
+ self.vim.delete_sfp(sfp_vim_id)
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ task["error_msg"] = None
+ return None
+
+ except vimconn.vimconnException as e:
+ task["error_msg"] = self._format_vim_error_msg(str(e))
+ if isinstance(e, vimconn.vimconnNotFoundException):
+ # If not found mark as Done and fill error_msg
+ task["status"] = "FINISHED" # with FINISHED instead of DONE it will not be refreshing
+ return None
+ task["status"] = "FAILED"
+ return None