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
, account
):
36 riftcm_config_plugin
.RiftCMConfigPluginBase
.__init
__(self
, dts
, log
, loop
, account
)
37 self
._name
= account
.name
38 self
._type
= riftcm_config_plugin
.DEFAULT_CAP_TYPE
39 self
._rift
_install
_dir
= os
.environ
['RIFT_INSTALL']
40 self
._rift
_artif
_dir
= os
.environ
['RIFT_ARTIFACTS']
44 # Instantiate events that will handle RiftCA configuration requests
45 self
._events
= Events
.ConfigManagerEvents(dts
, log
, loop
, self
)
62 def vnfr(self
, vnfr_id
):
64 vnfr
= self
._rift
_vnfs
[vnfr_id
].vnfr
66 self
._log
.debug("RiftCA: Did not find VNFR %s in Rift plugin", vnfr_id
)
71 def get_service_name(self
, vnfr_id
):
72 vnfr
= self
.vnfr(vnfr_id
)
78 def notify_create_vlr(self
, agent_nsr
, agent_vnfr
, vld
, vlr
):
80 Notification of create VL record
85 def is_vnf_configurable(self
, agent_vnfr
):
87 This needs to be part of abstract class
92 # Set this VNF's configurability status (need method to check)
93 yield from asyncio
.sleep(2, loop
=self
._loop
)
95 def riftca_log(self
, name
, level
, log_str
, *args
):
96 getattr(self
._log
, level
)('RiftCA:({}) {}'.format(name
, log_str
), *args
)
99 def notify_create_vnfr(self
, agent_nsr
, agent_vnfr
):
101 Notification of create Network VNF record
103 # Deploy the charm if specified for the vnf
104 self
._log
.debug("Rift config agent: create vnfr nsr={} vnfr={}"
105 .format(agent_nsr
.name
, agent_vnfr
.name
))
107 self
._loop
.create_task(self
.is_vnf_configurable(agent_vnfr
))
108 except Exception as e
:
109 self
._log
.debug("Rift config agent: vnf_configuration error for VNF:%s/%s: %s",
110 agent_nsr
.name
, agent_vnfr
.name
, str(e
))
116 def notify_instantiate_vnfr(self
, agent_nsr
, agent_vnfr
):
118 Notification of Instantiate NSR with the passed nsr id
123 def notify_instantiate_vlr(self
, agent_nsr
, agent_vnfr
, vlr
):
125 Notification of Instantiate NSR with the passed nsr id
130 def notify_terminate_vnfr(self
, agent_nsr
, agent_vnfr
):
132 Notification of Terminate the network service
136 def notify_terminate_vlr(self
, agent_nsr
, agent_vnfr
, vlr
):
138 Notification of Terminate the virtual link
143 def vnf_config_primitive(self
, agent_nsr
, agent_vnfr
, primitive
, output
):
145 primitives support by RiftCA
150 def apply_config(self
, config
, nsr
, vnfr
, rpc_ip
):
151 """ Notification on configuration of an NSR """
155 def apply_ns_config(self
, agent_nsr
, agent_vnfrs
, rpc_ip
):
156 """Hook: Runs the user defined script. Feeds all the necessary data
157 for the script thro' yaml file.
160 rpc_ip (YangInput_Nsr_ExecNsConfigPrimitive): The input data.
161 nsr (NetworkServiceRecord): Description
162 vnfrs (dict): VNFR ID => VirtualNetworkFunctionRecord
165 def xlate(tag
, tags
):
167 if tag
is None or tags
is None:
170 if re
.search('<.*>', tag
):
172 if tag
== '<rw_mgmt_ip>':
173 val
= tags
['rw_mgmt_ip']
174 except KeyError as e
:
175 self
._log
.info("RiftCA: Did not get a value for tag %s, e=%s",
179 def get_meta(agent_nsr
, agent_vnfrs
):
180 unit_names
, initial_params
, vnfr_index_map
, vnfr_data_map
= {}, {}, {}, {}
182 for vnfr_id
in agent_nsr
.vnfr_ids
:
183 vnfr
= agent_vnfrs
[vnfr_id
]
186 vnfr_index_map
[vnfr
.member_vnf_index
] = vnfr_id
187 vnfr_data_dict
= dict()
188 if 'mgmt_interface' in vnfr
.vnfr
:
189 vnfr_data_dict
['mgmt_interface'] = vnfr
.vnfr
['mgmt_interface']
191 vnfr_data_dict
['connection_point'] = []
192 if 'connection_point' in vnfr
.vnfr
:
193 for cp
in vnfr
.vnfr
['connection_point']:
195 cp_dict
['name'] = cp
['name']
196 cp_dict
['ip_address'] = cp
['ip_address']
197 vnfr_data_dict
['connection_point'].append(cp_dict
)
199 vnfr_data_dict
['vdur'] = []
200 vdu_data
= [(vdu
['name'], vdu
['management_ip'], vdu
['vm_management_ip'], vdu
['id'])
201 for vdu
in vnfr
.vnfr
['vdur']]
203 for data
in vdu_data
:
204 data
= dict(zip(['name', 'management_ip', 'vm_management_ip', 'id'] , data
))
205 vnfr_data_dict
['vdur'].append(data
)
207 vnfr_data_map
[vnfr
.member_vnf_index
] = vnfr_data_dict
209 unit_names
[vnfr_id
] = vnfr
.name
210 # Flatten the data for simplicity
212 if 'initial_config_primitive' in vnfr
.vnf_configuration
:
213 for primitive
in vnfr
.vnf_configuration
['initial_config_primitive']:
214 for parameter
in primitive
.parameter
:
215 value
= xlate(parameter
.value
, vnfr
.tags
)
216 param_data
[parameter
.name
] = value
218 initial_params
[vnfr_id
] = param_data
221 return unit_names
, initial_params
, vnfr_index_map
, vnfr_data_map
223 unit_names
, init_data
, vnfr_index_map
, vnfr_data_map
= get_meta(agent_nsr
, agent_vnfrs
)
224 # The data consists of 4 sections
226 # 2. The input passed.
227 # 3. Unit names (keyed by vnfr ID).
228 # 4. Initial config data (keyed by vnfr ID).
230 data
['config_agent'] = dict(
233 data
["rpc_ip"] = rpc_ip
.as_dict()
234 data
["unit_names"] = unit_names
235 data
["init_config"] = init_data
236 data
["vnfr_index_map"] = vnfr_index_map
237 data
["vnfr_data_map"] = vnfr_data_map
240 with tempfile
.NamedTemporaryFile(delete
=False) as tmp_file
:
241 tmp_file
.write(yaml
.dump(data
, default_flow_style
=True)
244 # Get the full path to the script
246 if rpc_ip
.user_defined_script
[0] == '/':
247 # The script has full path, use as is
248 script
= rpc_ip
.user_defined_script
250 script
= os
.path
.join(self
._rift
_artif
_dir
, 'launchpad/libs', agent_nsr
.nsd_id
, 'scripts',
251 rpc_ip
.user_defined_script
)
252 self
._log
.debug("Rift config agent: Checking for script in %s", script
)
253 if not os
.path
.exists(script
):
254 self
._log
.debug("Rift config agent: Did not find scipt %s", script
)
255 script
= os
.path
.join(self
._rift
_install
_dir
, 'usr/bin', rpc_ip
.user_defined_script
)
257 cmd
= "{} {}".format(script
, tmp_file
.name
)
258 self
._log
.debug("Rift config agent: Running the CMD: {}".format(cmd
))
260 coro
= asyncio
.create_subprocess_shell(cmd
, loop
=self
._loop
,
261 stderr
=asyncio
.subprocess
.PIPE
)
262 process
= yield from coro
263 err
= yield from process
.stderr
.read()
264 task
= self
._loop
.create_task(process
.wait())
269 def apply_initial_config(self
, agent_nsr
, agent_vnfr
):
271 Apply the initial configuration
274 self
._log
.debug("Rift config agent: Apply initial config to VNF:%s/%s",
275 agent_nsr
.name
, agent_vnfr
.name
)
277 if agent_vnfr
.id in self
._rift
_vnfs
.keys():
278 # Check if VNF instance is configurable (TBD - future)
279 ### Remove this once is_vnf_configurable() is implemented
280 agent_vnfr
.set_to_configurable()
281 if agent_vnfr
.is_configurable
:
282 # apply initial config for the vnfr
283 rc
= yield from self
._events
.apply_vnf_config(agent_vnfr
.vnf_cfg
)
285 self
._log
.info("Rift config agent: VNF:%s/%s is not configurable yet!",
286 agent_nsr
.name
, agent_vnfr
.name
)
287 except Exception as e
:
288 self
._log
.error("Rift config agent: Error on initial configuration to VNF:{}/{}, e {}"
289 .format(agent_nsr
.name
, agent_vnfr
.name
, str(e
)))
291 self
._log
.exception(e
)
296 def is_vnfr_managed(self
, vnfr_id
):
298 if vnfr_id
in self
._rift
_vnfs
:
300 except Exception as e
:
301 self
._log
.debug("Rift config agent: Is VNFR {} managed: {}".
305 def add_vnfr_managed(self
, agent_vnfr
):
306 if agent_vnfr
.id not in self
._rift
_vnfs
.keys():
307 self
._log
.info("Rift config agent: add vnfr={}/{}".format(agent_vnfr
.name
, agent_vnfr
.id))
308 self
._rift
_vnfs
[agent_vnfr
.id] = agent_vnfr
311 def get_config_status(self
, agent_nsr
, agent_vnfr
):
312 if agent_vnfr
.id in self
._rift
_vnfs
.keys():
317 def get_action_status(self
, execution_id
):
318 ''' Get the action status for an execution ID
319 *** Make sure this is NOT a asyncio coroutine function ***