2 # Copyright 2016 RIFT.IO Inc
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
18 import concurrent
.futures
24 from gi
.repository
import (
28 from . import riftcm_config_plugin
29 from . import rwconman_events
as Events
31 class RiftCAConfigPlugin(riftcm_config_plugin
.RiftCMConfigPluginBase
):
33 Implementation of the riftcm_config_plugin.RiftCMConfigPluginBase
35 def __init__(self
, dts
, log
, loop
, project
, account
):
36 riftcm_config_plugin
.RiftCMConfigPluginBase
.__init
__(self
, dts
, log
,
37 loop
, project
, account
)
38 self
._name
= account
.name
39 self
._type
= riftcm_config_plugin
.DEFAULT_CAP_TYPE
40 self
._rift
_install
_dir
= os
.environ
['RIFT_INSTALL']
41 self
._rift
_artif
_dir
= os
.environ
['RIFT_ARTIFACTS']
45 # Instantiate events that will handle RiftCA configuration requests
46 self
._events
= Events
.ConfigManagerEvents(dts
, log
, loop
, self
)
63 def vnfr(self
, vnfr_id
):
65 vnfr
= self
._rift
_vnfs
[vnfr_id
].vnfr
67 self
._log
.debug("RiftCA: Did not find VNFR %s in Rift plugin", vnfr_id
)
72 def get_service_name(self
, vnfr_id
):
73 vnfr
= self
.vnfr(vnfr_id
)
79 def notify_create_vlr(self
, agent_nsr
, agent_vnfr
, vld
, vlr
):
81 Notification of create VL record
86 def is_vnf_configurable(self
, agent_vnfr
):
88 This needs to be part of abstract class
93 # Set this VNF's configurability status (need method to check)
94 yield from asyncio
.sleep(2, loop
=self
._loop
)
96 def riftca_log(self
, name
, level
, log_str
, *args
):
97 getattr(self
._log
, level
)('RiftCA:({}) {}'.format(name
, log_str
), *args
)
100 def notify_create_vnfr(self
, agent_nsr
, agent_vnfr
):
102 Notification of create Network VNF record
104 # Deploy the charm if specified for the vnf
105 self
._log
.debug("Rift config agent: create vnfr nsr={} vnfr={}"
106 .format(agent_nsr
.name
, agent_vnfr
.name
))
108 self
._loop
.create_task(self
.is_vnf_configurable(agent_vnfr
))
109 except Exception as e
:
110 self
._log
.debug("Rift config agent: vnf_configuration error for VNF:%s/%s: %s",
111 agent_nsr
.name
, agent_vnfr
.name
, str(e
))
117 def notify_instantiate_vnfr(self
, agent_nsr
, agent_vnfr
):
119 Notification of Instantiate NSR with the passed nsr id
124 def notify_instantiate_vlr(self
, agent_nsr
, agent_vnfr
, vlr
):
126 Notification of Instantiate NSR with the passed nsr id
131 def notify_terminate_vnfr(self
, agent_nsr
, agent_vnfr
):
133 Notification of Terminate the network service
137 def notify_terminate_vlr(self
, agent_nsr
, agent_vnfr
, vlr
):
139 Notification of Terminate the virtual link
144 def vnf_config_primitive(self
, agent_nsr
, agent_vnfr
, primitive
, output
):
146 primitives support by RiftCA
151 def apply_config(self
, config
, nsr
, vnfr
, rpc_ip
):
152 """ Notification on configuration of an NSR """
156 def apply_ns_config(self
, agent_nsr
, agent_vnfrs
, rpc_ip
):
157 """Hook: Runs the user defined script. Feeds all the necessary data
158 for the script thro' yaml file.
161 rpc_ip (YangInput_Nsr_ExecNsConfigPrimitive): The input data.
162 nsr (NetworkServiceRecord): Description
163 vnfrs (dict): VNFR ID => VirtualNetworkFunctionRecord
166 def xlate(tag
, tags
):
168 if tag
is None or tags
is None:
171 if re
.search('<.*>', tag
):
173 if tag
== '<rw_mgmt_ip>':
174 val
= tags
['rw_mgmt_ip']
175 except KeyError as e
:
176 self
._log
.info("RiftCA: Did not get a value for tag %s, e=%s",
180 def get_meta(agent_nsr
, agent_vnfrs
):
181 unit_names
, initial_params
, vnfr_index_map
, vnfr_data_map
= {}, {}, {}, {}
183 for vnfr_id
in agent_nsr
.vnfr_ids
:
184 vnfr
= agent_vnfrs
[vnfr_id
]
187 vnfr_index_map
[vnfr
.member_vnf_index
] = vnfr_id
188 vnfr_data_dict
= dict()
189 if 'mgmt_interface' in vnfr
.vnfr
:
190 vnfr_data_dict
['mgmt_interface'] = vnfr
.vnfr
['mgmt_interface']
192 vnfr_data_dict
['connection_point'] = []
193 if 'connection_point' in vnfr
.vnfr
:
194 for cp
in vnfr
.vnfr
['connection_point']:
196 cp_dict
['name'] = cp
['name']
197 cp_dict
['ip_address'] = cp
['ip_address']
198 vnfr_data_dict
['connection_point'].append(cp_dict
)
200 vnfr_data_dict
['vdur'] = []
201 vdu_data
= [(vdu
['name'], vdu
['management_ip'], vdu
['vm_management_ip'], vdu
['id'])
202 for vdu
in vnfr
.vnfr
['vdur']]
204 for data
in vdu_data
:
205 data
= dict(zip(['name', 'management_ip', 'vm_management_ip', 'id'] , data
))
206 vnfr_data_dict
['vdur'].append(data
)
208 vnfr_data_map
[vnfr
.member_vnf_index
] = vnfr_data_dict
210 unit_names
[vnfr_id
] = vnfr
.name
211 # Flatten the data for simplicity
213 if 'initial_config_primitive' in vnfr
.vnf_configuration
:
214 for primitive
in vnfr
.vnf_configuration
['initial_config_primitive']:
215 for parameter
in primitive
.parameter
:
216 value
= xlate(parameter
.value
, vnfr
.tags
)
217 param_data
[parameter
.name
] = value
219 initial_params
[vnfr_id
] = param_data
222 return unit_names
, initial_params
, vnfr_index_map
, vnfr_data_map
224 unit_names
, init_data
, vnfr_index_map
, vnfr_data_map
= get_meta(agent_nsr
, agent_vnfrs
)
225 # The data consists of 4 sections
227 # 2. The input passed.
228 # 3. Unit names (keyed by vnfr ID).
229 # 4. Initial config data (keyed by vnfr ID).
231 data
['config_agent'] = dict(
234 data
["rpc_ip"] = rpc_ip
.as_dict()
235 data
["unit_names"] = unit_names
236 data
["init_config"] = init_data
237 data
["vnfr_index_map"] = vnfr_index_map
238 data
["vnfr_data_map"] = vnfr_data_map
241 with tempfile
.NamedTemporaryFile(delete
=False) as tmp_file
:
242 tmp_file
.write(yaml
.dump(data
, default_flow_style
=True)
245 # Get the full path to the script
247 if rpc_ip
.user_defined_script
[0] == '/':
248 # The script has full path, use as is
249 script
= rpc_ip
.user_defined_script
251 script
= os
.path
.join(self
._rift
_artif
_dir
, 'launchpad/libs', agent_nsr
.nsd_id
, 'scripts',
252 rpc_ip
.user_defined_script
)
253 self
._log
.debug("Rift config agent: Checking for script in %s", script
)
254 if not os
.path
.exists(script
):
255 self
._log
.debug("Rift config agent: Did not find scipt %s", script
)
256 script
= os
.path
.join(self
._rift
_install
_dir
, 'usr/bin', rpc_ip
.user_defined_script
)
258 cmd
= "{} {}".format(script
, tmp_file
.name
)
259 self
._log
.debug("Rift config agent: Running the CMD: {}".format(cmd
))
261 coro
= asyncio
.create_subprocess_shell(cmd
, loop
=self
._loop
,
262 stderr
=asyncio
.subprocess
.PIPE
)
263 process
= yield from coro
264 err
= yield from process
.stderr
.read()
265 task
= self
._loop
.create_task(process
.wait())
270 def apply_initial_config(self
, agent_nsr
, agent_vnfr
):
272 Apply the initial configuration
275 self
._log
.debug("Rift config agent: Apply initial config to VNF:%s/%s",
276 agent_nsr
.name
, agent_vnfr
.name
)
278 if agent_vnfr
.id in self
._rift
_vnfs
.keys():
279 # Check if VNF instance is configurable (TBD - future)
280 ### Remove this once is_vnf_configurable() is implemented
281 agent_vnfr
.set_to_configurable()
282 if agent_vnfr
.is_configurable
:
283 # apply initial config for the vnfr
284 rc
= yield from self
._events
.apply_vnf_config(agent_vnfr
.vnf_cfg
)
286 self
._log
.info("Rift config agent: VNF:%s/%s is not configurable yet!",
287 agent_nsr
.name
, agent_vnfr
.name
)
288 except Exception as e
:
289 self
._log
.error("Rift config agent: Error on initial configuration to VNF:{}/{}, e {}"
290 .format(agent_nsr
.name
, agent_vnfr
.name
, str(e
)))
292 self
._log
.exception(e
)
297 def is_vnfr_managed(self
, vnfr_id
):
299 if vnfr_id
in self
._rift
_vnfs
:
301 except Exception as e
:
302 self
._log
.debug("Rift config agent: Is VNFR {} managed: {}".
306 def add_vnfr_managed(self
, agent_vnfr
):
307 if agent_vnfr
.id not in self
._rift
_vnfs
.keys():
308 self
._log
.info("Rift config agent: add vnfr={}/{}".format(agent_vnfr
.name
, agent_vnfr
.id))
309 self
._rift
_vnfs
[agent_vnfr
.id] = agent_vnfr
312 def get_config_status(self
, agent_nsr
, agent_vnfr
):
313 if agent_vnfr
.id in self
._rift
_vnfs
.keys():
318 def get_action_status(self
, execution_id
):
319 ''' Get the action status for an execution ID
320 *** Make sure this is NOT a asyncio coroutine function ***