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.
26 from urllib
.parse
import urlparse
28 gi
.require_version('RwDts', '1.0')
29 from gi
.repository
import (
32 gi
.require_version('RwKeyspec', '1.0')
33 from gi
.repository
.RwKeyspec
import quoted_key
35 # Default config agent plugin type
36 DEFAULT_CAP_TYPE
= "riftca"
41 def nsr_opdata(k
=None):
42 return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
43 ("[nsr:ns-instance-config-ref={}]".format(quoted_key(k
)) if k
is not None else ""))
47 return ("C,/nsd:nsd-catalog/nsd:nsd" +
48 "[nsd:id={}]".format(quoted_key(k
)) if k
is not None else "")
51 def vnfr_opdata(k
=None):
52 return ("D,/vnfr:vnfr-catalog/vnfr:vnfr" +
53 ("[vnfr:id={}]".format(quoted_key(k
)) if k
is not None else ""))
56 def nsr_config(k
=None):
57 return ("C,/nsr:ns-instance-config/nsr:nsr[nsr:id={}]".format(quoted_key(k
)) if k
is not None else "")
60 class RiftCMnsr(object):
63 created for Agents to use objects from NSR
65 def __init__(self
, nsr_dict
, cfg
, project
):
68 self
._project
= project
76 return self
._nsr
['name_ref']
80 return self
._nsr
['nsd_name_ref']
84 return self
._nsr
['nsd_ref']
88 return self
._nsr
['ns_instance_config_ref']
95 def nsr_cfg_msg(self
):
104 ''' Get a new job id for config primitive'''
113 def member_vnf_index(self
):
114 return self
._vnfr
['member_vnf_index_ref']
116 def add_vnfr(self
, vnfr
, vnfr_msg
):
117 if vnfr
['id'] in self
._vnfr
_ids
.keys():
118 agent_vnfr
= self
._vnfr
_ids
[vnfr
['id']]
120 agent_vnfr
= RiftCMvnfr(self
.name
, vnfr
, vnfr_msg
, self
._project
)
121 self
._vnfrs
.append(agent_vnfr
)
122 self
._vnfrs
_msg
.append(vnfr_msg
)
123 self
._vnfr
_ids
[agent_vnfr
.id] = agent_vnfr
128 return self
._vnfr
_ids
130 def get_member_vnfr(self
, member_index
):
131 for vnfr
in self
._vnfrs
:
132 if vnfr
.member_vnf_index
== member_index
:
136 class RiftCMvnfr(object):
138 Agent base class for VNFR processing
140 def __init__(self
, nsr_name
, vnfr_dict
, vnfr_msg
, project
):
141 self
._vnfr
= vnfr_dict
142 self
._vnfr
_msg
= vnfr_msg
143 self
._vnfd
_msg
= vnfr_msg
.vnfd
144 self
._nsr
_name
= nsr_name
145 self
._configurable
= False
146 self
._project
= project
151 return self
._nsr
_name
159 return self
._vnfr
_msg
163 return self
._vnfd
_msg
167 return self
._vnfr
['name']
172 return self
._vnfr
['tags']
178 return self
._vnfr
['id']
181 def member_vnf_index(self
):
182 return self
._vnfr
['member_vnf_index_ref']
185 def vnf_configuration(self
):
186 return self
._vnfr
['vnf_configuration']
191 return self
._project
.add_project("D,/vnfr:vnfr-catalog/vnfr:vnfr[vnfr:id={}]".
192 format(quoted_key(self
.id)))
194 def set_to_configurable(self
):
195 self
._configurable
= True
198 def is_configurable(self
):
199 return self
._configurable
203 return self
._vnfr
['vnf_cfg']
210 def error(self
, value
):
214 class RiftCMConfigPluginBase(object):
216 Abstract base class for the NSM Configuration agent plugin.
217 There will be single instance of this plugin for each plugin type.
220 def __init__(self
, dts
, log
, loop
, project
, config_agent
):
224 self
._project
= project
225 self
._config
_agent
= config_agent
228 def agent_type(self
):
229 raise NotImplementedError
233 raise NotImplementedError
236 def agent_data(self
):
237 raise NotImplementedError
256 def vnfr(self
, vnfr_id
):
257 raise NotImplementedError
260 def get_Service_name(self
):
261 """ Get the service name specific to the plugin """
266 def apply_config(self
, agent_nsr
, agent_vnfr
, config
, rpc_ip
):
267 """ Notification on configuration of an NSR """
272 def apply_ns_config(self
, agent_nsr
, agent_vnfrs
, config
, rpc_ip
):
273 """ Notification on configuration of an NSR """
278 def notify_create_vlr(self
, agent_nsr
, vld
):
279 """ Notification on creation of an VL """
284 def notify_create_vnfr(self
, agent_nsr
, agent_vnfr
):
285 """ Notification on creation of an VNFR """
290 def notify_instantiate_vnfr(self
, agent_nsr
, agent_vnfr
):
291 """ Notify instantiation of the virtual network function """
296 def notify_instantiate_vlr(self
, agent_nsr
, vl
):
297 """ Notify instantiate of the virtual link"""
302 def notify_terminate_vnfr(self
, agent_nsr
, agent_vnfr
):
303 """Notify termination of the VNF """
308 def notify_terminate_vlr(self
, agent_nsr
, vlr
):
309 """Notify termination of the Virtual Link Record"""
314 def apply_initial_config(self
, vnfr_id
, vnf
):
315 """Apply initial configuration"""
320 def get_config_status(self
, vnfr_id
):
321 """Get the status for the VNF"""
325 def get_action_status(self
, execution_id
):
326 """Get the action exection status"""
331 def vnf_config_primitive(self
, nsr_id
, vnfr_id
, primitive
, output
):
332 """Apply config primitive on a VNF"""
336 def is_vnfr_managed(self
, vnfr_id
):
337 """ Check if VNR is managed by config agent """
341 def add_vnfr_managed(self
, agent_vnfr
):
342 """ Add VNR to be managed by this config agent """
345 def get_service_status(self
, vnfr_id
):
346 """Get the status of the service"""
351 def convert_value(self
, value
, type_
='STRING'):
352 if type_
== 'STRING':
353 if value
.startswith('file://'):
355 with
open(p
[2], 'r') as f
:
360 if type_
== 'INTEGER':
363 if type_
== 'BOOLEAN':
364 return (value
== 1) or (value
.lower() == 'true')
369 def _read_dts(self
, path
, do_trace
=False):
370 xpath
= self
._project
.add_project(path
)
371 self
._log
.debug("_read_dts path = %s", xpath
)
372 flags
= rwdts
.XactFlag
.MERGE
373 res_iter
= yield from self
._dts
.query_read(
380 result
= yield from i
381 if result
is not None:
382 results
.append(result
.result
)
390 def get_xpath(self
, xpath
):
391 self
._log
.debug("Attempting to get xpath: {}".format(xpath
))
392 resp
= yield from self
._read
_dts
(xpath
, False)
394 self
._log
.debug("Got DTS resp: {}".format(resp
[0]))
399 def get_nsr(self
, id):
400 self
._log
.debug("Attempting to get NSR: %s", id)
401 nsrl
= yield from self
._read
_dts
(XPaths
.nsr_opdata(id), False)
404 nsr
= nsrl
[0].as_dict()
408 def get_nsr_config(self
, id):
409 self
._log
.debug("Attempting to get config NSR: %s", id)
410 nsrl
= yield from self
._read
_dts
(XPaths
.nsr_config(id), False)
417 def get_vnfr(self
, id):
418 self
._log
.debug("Attempting to get VNFR: %s", id)
419 vnfrl
= yield from self
._read
_dts
(XPaths
.vnfr_opdata(id), do_trace
=False)
426 def exec_script(self
, script
, data
):
427 """Execute a shell script with the data as yaml input file"""
428 self
._log
.debug("Execute script {} with data {}".
429 format(script
, data
))
431 #Make the script executable if it is not.
432 perm
= os
.stat(script
).st_mode
433 if not (perm
& stat
.S_IXUSR
):
434 self
._log
.warning("script {} without execute permission: {}".
435 format(script
, perm
))
436 os
.chmod(script
, perm | stat
.S_IXUSR
)
439 with tempfile
.NamedTemporaryFile(delete
=False) as tmp_file
:
440 tmp_file
.write(yaml
.dump(data
, default_flow_style
=True)
443 cmd
= "{} {}".format(script
, tmp_file
.name
)
444 self
._log
.debug("Running the CMD: {}".format(cmd
))
447 proc
= yield from asyncio
.create_subprocess_shell(
449 stdout
=asyncio
.subprocess
.PIPE
,
450 stderr
=asyncio
.subprocess
.PIPE
)
451 rc
= yield from proc
.wait()
452 script_out
, script_err
= yield from proc
.communicate()
454 except Exception as e
:
455 msg
= "Script {} caused exception: {}". \
457 self
._log
.exception(msg
)
463 # Remove the tempfile created
466 os
.remove(tmp_file
.name
)
468 self
._log
.info("Error removing tempfile {}: {}".
469 format(tmp_file
.name
, e
))
472 if not os
.path
.exists(script
) :
473 self
._log
.error("Script {} not found: ".format(script
))
475 self
._log
.error("Script {}: rc={}\nStdOut:{}\nStdErr:{} \nPermissions on script: {}".
476 format(script
, rc
, script_out
, script_err
, stat
.filemode(os
.stat(script
).st_mode
)))
478 return rc
, script_err
481 def invoke(self
, method
, *args
):
484 self
._log
.debug("Config agent plugin: method {} with args {}: {}".
485 format(method
, args
, self
))
487 # TBD - Do a better way than string compare to find invoke the method
488 if method
== 'notify_create_nsr':
489 rc
= yield from self
.notify_create_nsr(args
[0], args
[1])
490 elif method
== 'notify_create_vlr':
491 rc
= yield from self
.notify_create_vlr(args
[0], args
[1], args
[2])
492 elif method
== 'notify_create_vnfr':
493 rc
= yield from self
.notify_create_vnfr(args
[0], args
[1])
494 elif method
== 'notify_instantiate_nsr':
495 rc
= yield from self
.notify_instantiate_nsr(args
[0])
496 elif method
== 'notify_instantiate_vnfr':
497 rc
= yield from self
.notify_instantiate_vnfr(args
[0], args
[1])
498 elif method
== 'notify_instantiate_vlr':
499 rc
= yield from self
.notify_instantiate_vlr(args
[0], args
[1])
500 elif method
== 'notify_nsr_active':
501 rc
= yield from self
.notify_nsr_active(args
[0], args
[1])
502 elif method
== 'notify_terminate_nsr':
503 rc
= yield from self
.notify_terminate_nsr(args
[0])
504 elif method
== 'notify_terminate_vnfr':
505 rc
= yield from self
.notify_terminate_vnfr(args
[0], args
[1])
506 elif method
== 'notify_terminate_vlr':
507 rc
= yield from self
.notify_terminate_vlr(args
[0], args
[1])
508 elif method
== 'apply_initial_config':
509 rc
= yield from self
.apply_initial_config(args
[0], args
[1])
510 elif method
== 'apply_config':
511 rc
= yield from self
.apply_config(args
[0], args
[1], args
[2])
512 elif method
== 'get_config_status':
513 rc
= yield from self
.get_config_status(args
[0], args
[1])
515 self
._log
.error("Unknown method %s invoked on config agent plugin",
517 except Exception as e
:
518 self
._log
.exception("Caught exception while invoking method: %s, "
519 "Exception: %s", method
, str(e
))