274 lines
12 KiB
Python
274 lines
12 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import ast
|
|
|
|
from tacker.mistral import workflow_generator
|
|
|
|
|
|
OUTPUT = {
|
|
'create_vnf': ['vnf_id', 'vim_id', 'mgmt_url', 'status'],
|
|
'create_vnffg': ['vnffg_id'],
|
|
}
|
|
|
|
|
|
class WorkflowGenerator(workflow_generator.WorkflowGeneratorBase):
|
|
|
|
def _add_create_vnf_tasks(self, ns):
|
|
vnfds = ns['vnfd_details']
|
|
task_dict = dict()
|
|
for vnfd_name, vnfd_info in (vnfds).items():
|
|
nodes = vnfd_info['instances']
|
|
for node in nodes:
|
|
task = self.wf_name + '_' + node
|
|
task_dict[task] = {
|
|
'action': 'tacker.create_vnf body=<% $.ns.{0} '
|
|
'%>'.format(node),
|
|
'input': {'body': '<% $.ns.{0} %>'.format(node)},
|
|
'publish': {
|
|
'vnf_id_' + node: '<% task({0}).result.vnf.id '
|
|
'%>'.format(task),
|
|
'vim_id_' + node: '<% task({0}).result.vnf.vim_id'
|
|
' %>'.format(task),
|
|
'mgmt_url_' + node: '<% task({0}).result.vnf.mgmt_url'
|
|
' %>'.format(task),
|
|
'status_' + node: '<% task({0}).result.vnf.status'
|
|
' %>'.format(task),
|
|
},
|
|
'on-success': ['wait_vnf_active_%s' % node]
|
|
}
|
|
return task_dict
|
|
|
|
def _add_wait_vnf_tasks(self, ns):
|
|
vnfds = ns['vnfd_details']
|
|
task_dict = dict()
|
|
for vnfd_name, vnfd_info in (vnfds).items():
|
|
nodes = vnfd_info['instances']
|
|
for node in nodes:
|
|
task = 'wait_vnf_active_%s' % node
|
|
task_dict[task] = {
|
|
'action': 'tacker.show_vnf vnf=<% $.vnf_id_{0} '
|
|
'%>'.format(node),
|
|
'retry': {
|
|
'count': 10,
|
|
'delay': 10,
|
|
'break-on': '<% $.status_{0} = "ACTIVE" '
|
|
'%>'.format(node),
|
|
'break-on': '<% $.status_{0} = "ERROR"'
|
|
' %>'.format(node),
|
|
'continue-on': '<% $.status_{0} = "PENDING_CREATE" '
|
|
'%>'.format(node),
|
|
},
|
|
'publish': {
|
|
'mgmt_url_' + node: ' <% task({0}).result.vnf.'
|
|
'mgmt_url %>'.format(task),
|
|
'status_' + node: '<% task({0}).result.vnf.status'
|
|
' %>'.format(task),
|
|
},
|
|
'on-success': [
|
|
{'delete_vnf_' + node: '<% $.status_{0}='
|
|
'"ERROR" %>'.format(node)}
|
|
]
|
|
}
|
|
vnffgd_templates = ns.get('vnffgd_templates')
|
|
if vnffgd_templates:
|
|
for vnffg_name in vnffgd_templates:
|
|
vnffg_group = vnffgd_templates[vnffg_name][
|
|
'topology_template']['groups'][vnffg_name]
|
|
constituent_vnfs = vnffg_group[
|
|
'properties']['constituent_vnfs']
|
|
|
|
if vnfd_name in constituent_vnfs:
|
|
task_dict[task]['on-success'].append(
|
|
'create_vnffg_%s' % vnffg_name)
|
|
return task_dict
|
|
|
|
def _add_delete_vnf_tasks(self, ns, vnffg_ids=None):
|
|
vnfds = ns['vnfd_details']
|
|
task_dict = dict()
|
|
for vnfd_name, vnfd_info in (vnfds).items():
|
|
nodes = vnfd_info['instances']
|
|
for node in nodes:
|
|
task = 'delete_vnf_%s' % node
|
|
task_dict[task] = {
|
|
'action': 'tacker.delete_vnf vnf=<% $.vnf_id_{0}'
|
|
'%>'.format(node),
|
|
}
|
|
if vnffg_ids and len(vnffg_ids):
|
|
task_dict[task].update({'join': 'all'})
|
|
return task_dict
|
|
|
|
def _add_create_vnffg_task(self, vnffgd_templates):
|
|
task_dict = dict()
|
|
previous_task = None
|
|
for vnffg_name in vnffgd_templates:
|
|
task = 'create_vnffg_%s' % vnffg_name
|
|
vnffg_output = 'vnffg_id_%s' % vnffg_name
|
|
task_dict[task] = {
|
|
'join': 'all',
|
|
'action': 'tacker.create_vnffg body=<% $.ns.{0} '
|
|
'%>'.format(vnffg_name),
|
|
'input': {'body': '<% $.ns.{0} %>'.format(vnffg_name)},
|
|
'publish': {
|
|
vnffg_output: '<% task({0}).result.'
|
|
'vnffg.id %>'.format(task)}
|
|
}
|
|
if previous_task:
|
|
task_dict[previous_task].update({'on-success': [task]})
|
|
previous_task = task
|
|
return task_dict
|
|
|
|
def _add_delete_vnffg_task(self, ns):
|
|
task_dict = dict()
|
|
vnfds = ns['vnfd_details']
|
|
vnffg_ids = ns['vnffg_details']
|
|
delayed_tasks = list()
|
|
|
|
for vnfd_name, vnfd_info in (vnfds).items():
|
|
nodes = vnfd_info['instances']
|
|
for node in nodes:
|
|
wait_task = 'delete_vnf_%s' % node
|
|
delayed_tasks.append(wait_task)
|
|
|
|
previous_task = None
|
|
for vnffg_name in vnffg_ids.keys():
|
|
task = 'delete_vnffg_%s' % vnffg_name
|
|
if previous_task:
|
|
wait_tasks = delayed_tasks + [previous_task]
|
|
else:
|
|
wait_tasks = delayed_tasks
|
|
previous_task = task
|
|
task_dict[task] = {
|
|
'action': 'tacker.delete_vnffg vnffg=<% $.{0} '
|
|
'%>'.format(vnffg_name),
|
|
'on-success': wait_tasks
|
|
}
|
|
return task_dict
|
|
|
|
def _build_output_dict(self, ns):
|
|
vnfds = ns['vnfd_details']
|
|
task_dict = dict()
|
|
for vnfd_name, vnfd_info in (vnfds).items():
|
|
nodes = vnfd_info['instances']
|
|
for node in nodes:
|
|
for op_name in OUTPUT['create_vnf']:
|
|
task_dict[op_name + '_' + node] = \
|
|
'<% $.{0}_{1} %>'.format(op_name, node)
|
|
vnffgd_templates = ns.get('vnffgd_templates')
|
|
if vnffgd_templates:
|
|
for vnffg_name in vnffgd_templates:
|
|
for op_name in OUTPUT['create_vnffg']:
|
|
vnffg_output = '%s_%s' % (op_name, vnffg_name)
|
|
task_dict[vnffg_output] = \
|
|
'<% $.{0}_{1} %>'.format(op_name, vnffg_name)
|
|
return task_dict
|
|
|
|
def get_input_dict(self):
|
|
return self.input_dict
|
|
|
|
def build_input(self, ns, params):
|
|
vnfds = ns['vnfd_details']
|
|
ns_id = ns['ns'].get('ns_id')
|
|
ns_name = ns['ns'].get('name')
|
|
self.input_dict = {'ns': {}}
|
|
for vnfd_name, vnfd_info in (vnfds).items():
|
|
nodes = vnfd_info['instances']
|
|
for node in nodes:
|
|
vnf_name = '%s_VNF_%s' % (ns_name, vnfd_info['id'])
|
|
self.input_dict['ns'][node] = dict()
|
|
self.input_dict['ns'][node]['vnf'] = {
|
|
'attributes': {},
|
|
'vim_id': ns['ns'].get('vim_id', ''),
|
|
'vnfd_id': vnfd_info['id'],
|
|
'name': vnf_name
|
|
}
|
|
if params.get(vnfd_name):
|
|
self.input_dict['ns'][node]['vnf']['attributes'] = {
|
|
'param_values': params.get(vnfd_name)
|
|
}
|
|
if ns.get('vnffgd_templates'):
|
|
vnffg_input = self.build_vnffg_input(ns, params, ns_id)
|
|
self.input_dict['ns'].update(vnffg_input)
|
|
|
|
def build_vnffg_input(self, ns, params, ns_id):
|
|
vnffgd_templates = ns.get('vnffgd_templates')
|
|
vnffg_input = dict()
|
|
for vnffg_name in vnffgd_templates:
|
|
vnffg_group = vnffgd_templates[vnffg_name][
|
|
'topology_template']['groups'][vnffg_name]
|
|
constituent_vnfs = vnffg_group[
|
|
'properties']['constituent_vnfs']
|
|
vnf_mapping = self.get_vnf_mapping(ns, constituent_vnfs)
|
|
vnffgd_body = dict()
|
|
vnffgd_body['vnffg'] = {
|
|
'name': '%s_%s_%s' % (ns['ns'].get('name'), vnffg_name, ns_id),
|
|
'vnffgd_template': vnffgd_templates[vnffg_name],
|
|
'vnf_mapping': vnf_mapping,
|
|
'attributes': {
|
|
'param_values': params.get('nsd')},
|
|
'ns_id': ns_id
|
|
}
|
|
vnffg_input[vnffg_name] = vnffgd_body
|
|
return vnffg_input
|
|
|
|
def get_vnf_mapping(self, ns, constituent_vnfs):
|
|
vnfds = ns['vnfd_details']
|
|
vnf_mapping = dict()
|
|
for vnfd_name, vnfd_info in (vnfds).items():
|
|
if vnfd_name in constituent_vnfs:
|
|
vnf_name = '%s_VNF_%s' % (ns['ns'].get('name'),
|
|
vnfd_info['id'])
|
|
vnf_mapping[vnfd_name] = vnf_name
|
|
return vnf_mapping
|
|
|
|
def create_ns(self, **kwargs):
|
|
ns = kwargs.get('ns')
|
|
params = kwargs.get('params')
|
|
# TODO(anyone): Keep this statements in a loop and
|
|
# remove in all the methods.
|
|
self.definition[self.wf_identifier]['tasks'] = dict()
|
|
self.definition[self.wf_identifier]['tasks'].update(
|
|
self._add_create_vnf_tasks(ns))
|
|
self.definition[self.wf_identifier]['tasks'].update(
|
|
self._add_wait_vnf_tasks(ns))
|
|
self.definition[self.wf_identifier]['tasks'].update(
|
|
self._add_delete_vnf_tasks(ns))
|
|
self.definition[self.wf_identifier]['output'] = \
|
|
self._build_output_dict(ns)
|
|
self.build_input(ns, params)
|
|
vnffgd_templates = ns.get('vnffgd_templates')
|
|
if vnffgd_templates:
|
|
self.definition[self.wf_identifier]['tasks'].update(
|
|
self._add_create_vnffg_task(vnffgd_templates))
|
|
|
|
def delete_ns(self, ns):
|
|
ns_dict = {'vnfd_details': {}}
|
|
vnf_ids = ast.literal_eval(ns['vnf_ids'])
|
|
self.definition[self.wf_identifier]['input'] = []
|
|
for vnf in vnf_ids.keys():
|
|
vnf_key = 'vnf_id_' + vnf
|
|
self.definition[self.wf_identifier]['input'].append(vnf_key)
|
|
self.input_dict[vnf_key] = vnf_ids[vnf]
|
|
ns_dict['vnfd_details'][vnf] = {'instances': [vnf]}
|
|
self.definition[self.wf_identifier]['tasks'] = dict()
|
|
|
|
vnffg_ids = ast.literal_eval(ns.get('vnffg_ids'))
|
|
if len(vnffg_ids):
|
|
for vnffg_name in vnffg_ids.keys():
|
|
self.definition[self.wf_identifier]['input'].append(vnffg_name)
|
|
self.input_dict[vnffg_name] = vnffg_ids[vnffg_name]
|
|
ns_dict['vnffg_details'] = vnffg_ids
|
|
self.definition[self.wf_identifier]['tasks'].update(
|
|
self._add_delete_vnffg_task(ns_dict))
|
|
self.definition[self.wf_identifier]['tasks'].update(
|
|
self._add_delete_vnf_tasks(ns_dict, vnffg_ids))
|