COMPONENT ${PKG_LONG_NAME}
FILES
rift/mano/examples/ping_pong_nsd.py
+ rift/mano/examples/ping_setup.py
+ rift/mano/examples/ping_rate.py
+ rift/mano/examples/ping_start_stop.py
+ rift/mano/examples/pong_setup.py
+ rift/mano/examples/pong_start_stop.py
rift/mano/examples/start_traffic.py
)
install(
PROGRAMS
- rift/mano/examples/ping_config.py
+ rift/mano/examples/ping_scale.py
stand_up_ping_pong
DESTINATION usr/bin
COMPONENT ${PKG_LONG_NAME}
+++ /dev/null
-#!/usr/bin/env python3
-
-#
-# Copyright 2016 RIFT.IO Inc
-#
-# 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 argparse
-import logging
-import os
-import stat
-import subprocess
-import sys
-import time
-import yaml
-
-def ping_config(run_dir, mgmt_ip, mgmt_port, pong_cp, logger, dry_run):
- sh_file = "{}/ping_config-{}.sh".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
- logger.debug("Creating script file %s" % sh_file)
- f = open(sh_file, "w")
- f.write(r'''
-#!/bin/bash
-
-# Rest API config
-ping_mgmt_ip='{}'
-ping_mgmt_port={}
-
-# VNF specific configuration
-pong_server_ip='{}'
-ping_rate=5
-server_port=5555
-'''.format(mgmt_ip, mgmt_port, pong_cp))
-
- f.write(r'''
-# Check if the port is open
-DELAY=1
-MAX_TRIES=60
-COUNT=0
-while true; do
- COUNT=$(expr $COUNT + 1)
- timeout 1 bash -c "cat < /dev/null > /dev/tcp/${ping_mgmt_ip}/${ping_mgmt_port}"
- rc=$?
- if [ $rc -ne 0 ]
- then
- echo "Failed to connect to server ${ping_mgmt_ip}:${ping_mgmt_port} for ping with $rc!"
- if [ ${COUNT} -gt ${MAX_TRIES} ]; then
- exit $rc
- fi
- sleep ${DELAY}
- else
- break
- fi
-done
-
-# Make rest API calls to configure VNF
-curl -D /dev/stdout \
- -H "Accept: application/vnd.yang.data+xml" \
- -H "Content-Type: application/vnd.yang.data+json" \
- -X POST \
- -d "{\"ip\":\"$pong_server_ip\", \"port\":$server_port}" \
- http://${ping_mgmt_ip}:${ping_mgmt_port}/api/v1/ping/server
-rc=$?
-if [ $rc -ne 0 ]
-then
- echo "Failed to set server info for ping!"
- exit $rc
-fi
-
-curl -D /dev/stdout \
- -H "Accept: application/vnd.yang.data+xml" \
- -H "Content-Type: application/vnd.yang.data+json" \
- -X POST \
- -d "{\"rate\":$ping_rate}" \
- http://${ping_mgmt_ip}:${ping_mgmt_port}/api/v1/ping/rate
-rc=$?
-if [ $rc -ne 0 ]
-then
- echo "Failed to set ping rate!"
- exit $rc
-fi
-
-output=$(curl -D /dev/stdout \
- -H "Accept: application/vnd.yang.data+xml" \
- -H "Content-Type: application/vnd.yang.data+json" \
- -X POST \
- -d "{\"enable\":true}" \
- http://${ping_mgmt_ip}:${ping_mgmt_port}/api/v1/ping/adminstatus/state)
-if [[ $output == *"Internal Server Error"* ]]
-then
- echo $output
- exit 3
-else
- echo $output
-fi
-
-exit 0
-''')
- f.close()
- os.chmod(sh_file, stat.S_IRWXU)
- if not dry_run:
- rc = subprocess.call(sh_file, shell=True)
- if rc:
- logger.error("Config failed: {}".format(rc))
- return False
- return True
-
-
-
-def main(argv=sys.argv[1:]):
- try:
- parser = argparse.ArgumentParser()
- parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
- parser.add_argument("--dry-run", action="store_true")
- parser.add_argument("--quiet", "-q", dest="verbose", action="store_false")
- args = parser.parse_args()
-
- run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
- if not os.path.exists(run_dir):
- os.makedirs(run_dir)
- log_file = "{}/rift_ping_config-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
- logging.basicConfig(filename=log_file, level=logging.DEBUG)
- logger = logging.getLogger()
-
- ch = logging.StreamHandler()
- if args.verbose:
- ch.setLevel(logging.DEBUG)
- else:
- ch.setLevel(logging.INFO)
-
- # create formatter and add it to the handlers
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
- ch.setFormatter(formatter)
- logger.addHandler(ch)
-
- except Exception as e:
- print("Got exception:{}".format(e))
- raise e
-
- try:
- dry_run = args.dry_run
-
- yaml_str = args.yaml_cfg_file.read()
- logger.debug("Input YAML file: {}".format(yaml_str))
- yaml_cfg = yaml.load(yaml_str)
- logger.debug("Input YAML: {}".format(yaml_cfg))
-
- # Check if this is post scale out trigger
- if yaml_cfg['trigger'] != 'post_scale_out':
- logger.error("Unexpected trigger {}".
- format(yaml_cfg['trigger']))
- raise
-
- pong_cp = ""
- for vnfr in yaml_cfg['vnfrs_others']:
- # Find the pong VNFR, assuming vnfr name will
- # have pong_vnfd as a substring
- if 'pong_vnfd' in vnfr['name']:
- for cp in vnfr['connection_points']:
- logger.debug("Connection point {}".format(cp))
- if 'cp0' in cp['name']:
- pong_cp = cp['ip_address']
- break
- if not len(pong_cp):
- logger.error("Did not get Pong cp0 IP")
- raise
-
- for vnfr in yaml_cfg['vnfrs_in_group']:
- mgmt_ip = vnfr['rw_mgmt_ip']
- mgmt_port = vnfr['rw_mgmt_port']
- if ping_config(run_dir, mgmt_ip, mgmt_port, pong_cp, logger, dry_run):
- logger.info("Successfully configured Ping {} at {}".
- format(vnfr['name'], mgmt_ip))
- else:
- logger.error("Config of ping {} with {} failed".
- format(vnfr['name'], mgmt_ip))
- raise
-
- except Exception as e:
- logger.error("Got exception {}".format(e))
- logger.exception(e)
- raise e
-
-if __name__ == "__main__":
- main()
# Add vnf configuration
vnf_config = vnfd.vnf_configuration
- vnf_config.config_attributes.config_delay = 60
+ # vnf_config.config_attributes.config_delay = 10
# Select "script" configuration
vnf_config.script.script_type = 'bash'
{"name": "pong_port", "data_type": "INTEGER",
"default_value": "5555"},
],
- "user_defined_script": "ping-setup.py",
+ "user_defined_script": "ping_setup.py",
})
vnf_config.config_primitive.append(prim)
{"name": "rate", "data_type": "INTEGER",
"default_value": "5"},
],
- "user_defined_script": "ping-set-rate.py",
+ "user_defined_script": "ping_rate.py",
})
vnf_config.config_primitive.append(prim)
{"name": "start", "data_type": "BOOLEAN",
"default_value": "true"}
],
- "user_defined_script": "ping-start-stop.py",
+ "user_defined_script": "ping_start_stop.py",
})
vnf_config.config_primitive.append(prim)
{"name": "service_ip", "data_type": "STRING"},
{"name": "service_port", "data_type": "INTEGER"},
],
- "user_defined_script": "ping-setup.py",
+ "user_defined_script": "pong_setup.py",
})
vnf_config.config_primitive.append(prim)
{"name": "start", "data_type": "BOOLEAN",
"default_value": "true"}
],
- "user_defined_script": "ping-start-stop.py",
+ "user_defined_script": "pong_start_stop.py",
})
vnf_config.config_primitive.append(prim)
member_vdu.member_vdu_ref = vdu.id
- def write_to_file(self, outdir, output_format):
+ def write_to_file(self, outdir, output_format, use_vca_conf=False):
dirpath = "%s/%s" % (outdir, self.name)
if not os.path.exists(dirpath):
os.makedirs(dirpath)
super(VirtualNetworkFunction, self).write_to_file(['vnfd', 'rw-vnfd'],
dirpath,
output_format)
- self.add_scripts(outdir)
+ self.add_scripts(outdir, use_vca_conf=use_vca_conf)
- def add_scripts(self, outdir):
+ def add_cloud_init(self, outdir):
script_dir = os.path.join(outdir, self.name, 'cloud_init')
try:
os.makedirs(script_dir)
if not os.path.isdir(script_dir):
raise
- if 'ping' in self.name:
+ if 'ping_' in self.name:
script_file = os.path.join(script_dir, 'ping_cloud_init.cfg')
cfg = PING_USERDATA_FILE
else:
with open(script_file, "w") as f:
f.write("{}".format(cfg))
+ def add_scripts(self, outdir, use_vca_conf=False):
+ self.add_cloud_init(outdir)
+ if use_vca_conf:
+ self.add_vca_scripts(outdir)
+
+ def add_vca_scripts(self, outdir):
+ dest_path = os.path.join(outdir, self.name, 'scripts')
+ try:
+ os.makedirs(dest_path)
+ except OSError:
+ if not os.path.isdir(dest_path):
+ raise
+
+ if 'pong_' in self.name:
+ scripts = ['pong_setup.py', 'pong_start_stop.py']
+ else:
+ scripts = ['ping_setup.py', 'ping_rate.py', 'ping_start_stop.py']
+
+ for script_name in scripts:
+ src_path = os.path.dirname(os.path.abspath(
+ os.path.realpath(__file__)))
+ script_src = os.path.join(src_path, script_name)
+ if not os.path.exists(script_src):
+ src_path = os.path.join(os.environ['RIFT_ROOT'],
+ 'modules/core/mano/examples/'
+ 'ping_pong_ns/rift/mano/examples')
+ script_src = os.path.join(src_path, script_name)
+
+ shutil.copy2(script_src, dest_path)
class NetworkService(ManoDescriptor):
def __init__(self, name):
if mano_ut:
nsd.service_primitive.add().from_dict(
{
- "name": "ping config",
+ "name": "ping scale",
"user_defined_script": "{}".format(os.path.join(
os.environ['RIFT_ROOT'],
'modules/core/mano',
else:
nsd.service_primitive.add().from_dict(
{
- "name": "ping config",
- "user_defined_script": "ping_config.py"
+ "name": "ping scale",
+ "user_defined_script": "ping_scale.py"
})
def ns_initial_config(self, nsd):
vnfap_map.capability.member_vnf_index = 2
vnfap_map.capability.capability_ref = 'service_port'
vnfap_map.dependency.member_vnf_index = 1
- vnfap_map.dependency.dependency_ref = 'port_port'
+ vnfap_map.dependency.dependency_ref = 'pong_port'
def compose(self, vnfd_list, cpgroup_list, mano_ut,
use_ns_init_conf=True,
def add_config(self):
self.config_action['post_scale_out']= {'ns-config-primitive-name-ref':
- 'ping config'}
+ 'ping scale'}
class PlacementGroup(object):
def __init__(self, name):
)
if write_to_file:
- ping.write_to_file(out_dir, ping_fmt if ping_fmt is not None else fmt)
- pong.write_to_file(out_dir, pong_fmt if ping_fmt is not None else fmt)
+ ping.write_to_file(out_dir, ping_fmt if ping_fmt is not None else fmt,
+ use_vca_conf=use_vca_conf)
+ pong.write_to_file(out_dir, pong_fmt if ping_fmt is not None else fmt,
+ use_vca_conf=use_vca_conf)
nsd_catalog.write_config(out_dir, vnfd_list)
nsd_catalog.write_to_file(out_dir, ping_fmt if nsd_fmt is not None else fmt)
--- /dev/null
+#!/usr/bin/env python3
+
+############################################################################
+# Copyright 2016 RIFT.IO Inc #
+# #
+# 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 argparse
+import logging
+import os
+import subprocess
+import sys
+import time
+
+import yaml
+
+
+def ping_rate(yaml_cfg, logger):
+ '''Use curl to configure ping and set the ping rate'''
+
+ # Get the required and optional parameters
+ params = yaml_cfg['parameters']
+ mgmt_ip = params['mgmt_ip']
+ mgmt_port = 18888
+ if 'mgmt_port' in params:
+ mgmt_port = params['mgmt_port']
+ rate = 1
+ if 'rate' in params:
+ rate = params['rate']
+
+ cmd = 'curl -D /dev/stdout -H "Accept: application/vnd.yang.data' \
+ '+xml" -H "Content-Type: application/vnd.yang.data+json" ' \
+ '-X POST -d "{{\\"rate\\":{rate}}}" ' \
+ 'http://{mgmt_ip}:{mgmt_port}/api/v1/ping/rate'. \
+ format(
+ mgmt_ip=mgmt_ip,
+ mgmt_port=mgmt_port,
+ rate=rate)
+
+ logger.debug("Executing cmd: %s", cmd)
+ proc = subprocess.run(cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ logger.debug("Process: {}".format(proc))
+
+ return proc.returncode
+
+
+def main(argv=sys.argv[1:]):
+ try:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+ parser.add_argument("-q", "--quiet", dest="verbose", action="store_false")
+ args = parser.parse_args()
+
+ run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
+ if not os.path.exists(run_dir):
+ os.makedirs(run_dir)
+ log_file = "{}/ping_rate-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+
+ # logging.basicConfig(filename=log_file, level=logging.DEBUG)
+ logger = logging.getLogger('ping-rate')
+ logger.setLevel(logging.DEBUG)
+
+ fh = logging.FileHandler(log_file)
+ fh.setLevel(logging.DEBUG)
+
+ ch = logging.StreamHandler()
+ if args.verbose:
+ ch.setLevel(logging.DEBUG)
+ else:
+ ch.setLevel(logging.INFO)
+
+ # create formatter and add it to the handlers
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ fh.setFormatter(formatter)
+ ch.setFormatter(formatter)
+ logger.addHandler(fh)
+ logger.addHandler(ch)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+ try:
+ logger.debug("Input file: {}".format(args.yaml_cfg_file.name))
+ yaml_str = args.yaml_cfg_file.read()
+ yaml_cfg = yaml.load(yaml_str)
+ logger.debug("Input YAML: {}".format(yaml_cfg))
+
+ rc = ping_rate(yaml_cfg, logger)
+ logger.info("Return code: {}".format(rc))
+ sys.exit(rc)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/usr/bin/env python3
+
+#
+# Copyright 2016 RIFT.IO Inc
+#
+# 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 argparse
+import logging
+import os
+import stat
+import subprocess
+import sys
+import time
+import yaml
+
+def ping_config(run_dir, mgmt_ip, mgmt_port, pong_cp, logger, dry_run):
+ sh_file = "{}/ping_config-{}.sh".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+ logger.debug("Creating script file %s" % sh_file)
+ f = open(sh_file, "w")
+ f.write(r'''
+#!/bin/bash
+
+# Rest API config
+ping_mgmt_ip='{}'
+ping_mgmt_port={}
+
+# VNF specific configuration
+pong_server_ip='{}'
+ping_rate=5
+server_port=5555
+'''.format(mgmt_ip, mgmt_port, pong_cp))
+
+ f.write(r'''
+# Check if the port is open
+DELAY=1
+MAX_TRIES=60
+COUNT=0
+while true; do
+ COUNT=$(expr $COUNT + 1)
+ timeout 1 bash -c "cat < /dev/null > /dev/tcp/${ping_mgmt_ip}/${ping_mgmt_port}"
+ rc=$?
+ if [ $rc -ne 0 ]
+ then
+ echo "Failed to connect to server ${ping_mgmt_ip}:${ping_mgmt_port} for ping with $rc!"
+ if [ ${COUNT} -gt ${MAX_TRIES} ]; then
+ exit $rc
+ fi
+ sleep ${DELAY}
+ else
+ break
+ fi
+done
+
+# Make rest API calls to configure VNF
+curl -D /dev/stdout \
+ -H "Accept: application/vnd.yang.data+xml" \
+ -H "Content-Type: application/vnd.yang.data+json" \
+ -X POST \
+ -d "{\"ip\":\"$pong_server_ip\", \"port\":$server_port}" \
+ http://${ping_mgmt_ip}:${ping_mgmt_port}/api/v1/ping/server
+rc=$?
+if [ $rc -ne 0 ]
+then
+ echo "Failed to set server info for ping!"
+ exit $rc
+fi
+
+curl -D /dev/stdout \
+ -H "Accept: application/vnd.yang.data+xml" \
+ -H "Content-Type: application/vnd.yang.data+json" \
+ -X POST \
+ -d "{\"rate\":$ping_rate}" \
+ http://${ping_mgmt_ip}:${ping_mgmt_port}/api/v1/ping/rate
+rc=$?
+if [ $rc -ne 0 ]
+then
+ echo "Failed to set ping rate!"
+ exit $rc
+fi
+
+output=$(curl -D /dev/stdout \
+ -H "Accept: application/vnd.yang.data+xml" \
+ -H "Content-Type: application/vnd.yang.data+json" \
+ -X POST \
+ -d "{\"enable\":true}" \
+ http://${ping_mgmt_ip}:${ping_mgmt_port}/api/v1/ping/adminstatus/state)
+if [[ $output == *"Internal Server Error"* ]]
+then
+ echo $output
+ exit 3
+else
+ echo $output
+fi
+
+exit 0
+''')
+ f.close()
+ os.chmod(sh_file, stat.S_IRWXU)
+ if not dry_run:
+ rc = subprocess.call(sh_file, shell=True)
+ if rc:
+ logger.error("Config failed: {}".format(rc))
+ return False
+ return True
+
+
+
+def main(argv=sys.argv[1:]):
+ try:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+ parser.add_argument("--dry-run", action="store_true")
+ parser.add_argument("--quiet", "-q", dest="verbose", action="store_false")
+ args = parser.parse_args()
+
+ run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
+ if not os.path.exists(run_dir):
+ os.makedirs(run_dir)
+ log_file = "{}/rift_ping_config-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+ logging.basicConfig(filename=log_file, level=logging.DEBUG)
+ logger = logging.getLogger()
+
+ ch = logging.StreamHandler()
+ if args.verbose:
+ ch.setLevel(logging.DEBUG)
+ else:
+ ch.setLevel(logging.INFO)
+
+ # create formatter and add it to the handlers
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ ch.setFormatter(formatter)
+ logger.addHandler(ch)
+
+ except Exception as e:
+ print("Got exception:{}".format(e))
+ raise e
+
+ try:
+ dry_run = args.dry_run
+
+ yaml_str = args.yaml_cfg_file.read()
+ logger.debug("Input YAML file: {}".format(yaml_str))
+ yaml_cfg = yaml.load(yaml_str)
+ logger.debug("Input YAML: {}".format(yaml_cfg))
+
+ # Check if this is post scale out trigger
+ if yaml_cfg['trigger'] != 'post_scale_out':
+ logger.error("Unexpected trigger {}".
+ format(yaml_cfg['trigger']))
+ raise
+
+ pong_cp = ""
+ for vnfr in yaml_cfg['vnfrs_others']:
+ # Find the pong VNFR, assuming vnfr name will
+ # have pong_vnfd as a substring
+ if 'pong_vnfd' in vnfr['name']:
+ for cp in vnfr['connection_points']:
+ logger.debug("Connection point {}".format(cp))
+ if 'cp0' in cp['name']:
+ pong_cp = cp['ip_address']
+ break
+ if not len(pong_cp):
+ logger.error("Did not get Pong cp0 IP")
+ raise
+
+ for vnfr in yaml_cfg['vnfrs_in_group']:
+ mgmt_ip = vnfr['rw_mgmt_ip']
+ mgmt_port = vnfr['rw_mgmt_port']
+ if ping_config(run_dir, mgmt_ip, mgmt_port, pong_cp, logger, dry_run):
+ logger.info("Successfully configured Ping {} at {}".
+ format(vnfr['name'], mgmt_ip))
+ else:
+ logger.error("Config of ping {} with {} failed".
+ format(vnfr['name'], mgmt_ip))
+ raise
+
+ except Exception as e:
+ logger.error("Got exception {}".format(e))
+ logger.exception(e)
+ raise e
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/usr/bin/env python3
+
+############################################################################
+# Copyright 2016 RIFT.IO Inc #
+# #
+# 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 argparse
+import logging
+import os
+import subprocess
+import sys
+import time
+
+import yaml
+
+
+def ping_setup(yaml_cfg, logger):
+ '''Use curl to configure ping and set the ping rate'''
+
+ # Get the required and optional parameters
+ params = yaml_cfg['parameters']
+ mgmt_ip = params['mgmt_ip']
+ mgmt_port = 18888
+ if 'mgmt_port' in params:
+ mgmt_port = params['mgmt_port']
+ pong_ip = params['pong_ip']
+ pong_port = 5555
+ if 'pong_port' in params:
+ pong_port = params['pong_port']
+ rate = 1
+ if 'rate' in params:
+ rate = params['rate']
+
+ cmd = 'curl -D /dev/stdout -H "Accept: application/vnd.yang.data' \
+ '+xml" -H "Content-Type: application/vnd.yang.data+json" ' \
+ '-X POST -d "{{\\"ip\\":\\"{pong_ip}\\", \\"port\\":{pong_port}}}" ' \
+ 'http://{mgmt_ip}:{mgmt_port}/api/v1/ping/server'. \
+ format(
+ mgmt_ip=mgmt_ip,
+ mgmt_port=mgmt_port,
+ pong_ip=pong_ip,
+ pong_port=pong_port)
+
+ logger.debug("Executing cmd: %s", cmd)
+ count = 0
+ delay = 5
+ max_tries = 12
+ rc = 0
+
+ while True:
+ count += 1
+ proc = subprocess.run(cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ logger.debug("Process: {}".format(proc))
+
+ if proc.returncode == 0:
+ # Check if response is 200 OK
+ resp = proc.stdout.decode()
+ if 'HTTP/1.1 200 OK' in resp:
+ rc = 0
+ break
+ self._log.error("Got error response: {}".format(resp))
+ rc = 1
+ break
+
+ elif proc.returncode == 7:
+ # Connection timeout
+ if count >= max_tries:
+ self._log.error("Connect failed for {}. Failing".format(count))
+ rc = 7
+ break
+ # Try after delay
+ time.sleep(delay)
+
+ return rc
+
+def main(argv=sys.argv[1:]):
+ try:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+ parser.add_argument("-q", "--quiet", dest="verbose", action="store_false")
+ args = parser.parse_args()
+
+ run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
+ if not os.path.exists(run_dir):
+ os.makedirs(run_dir)
+ log_file = "{}/ping_setup-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+
+ # logging.basicConfig(filename=log_file, level=logging.DEBUG)
+ logger = logging.getLogger('ping-setup')
+ logger.setLevel(logging.DEBUG)
+
+ fh = logging.FileHandler(log_file)
+ fh.setLevel(logging.DEBUG)
+
+ ch = logging.StreamHandler()
+ if args.verbose:
+ ch.setLevel(logging.DEBUG)
+ else:
+ ch.setLevel(logging.INFO)
+
+ # create formatter and add it to the handlers
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ fh.setFormatter(formatter)
+ ch.setFormatter(formatter)
+ logger.addHandler(fh)
+ logger.addHandler(ch)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+ try:
+ logger.debug("Input file: {}".format(args.yaml_cfg_file.name))
+ yaml_str = args.yaml_cfg_file.read()
+ yaml_cfg = yaml.load(yaml_str)
+ logger.debug("Input YAML: {}".format(yaml_cfg))
+
+ rc = ping_setup(yaml_cfg, logger)
+ logger.info("Return code: {}".format(rc))
+ sys.exit(rc)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/usr/bin/env python3
+
+############################################################################
+# Copyright 2016 RIFT.IO Inc #
+# #
+# 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 argparse
+import logging
+import os
+import subprocess
+import sys
+import time
+
+import yaml
+
+
+def ping_start_stop(yaml_cfg, logger):
+ '''Use curl to configure ping and set the ping rate'''
+
+ # Get the required and optional parameters
+ params = yaml_cfg['parameters']
+ mgmt_ip = params['mgmt_ip']
+ mgmt_port = 18888
+ if 'mgmt_port' in params:
+ mgmt_port = params['mgmt_port']
+ start = 'true'
+ if 'start' in params:
+ if not params['start']:
+ start = 'false'
+
+ cmd = 'curl -D /dev/stdout -H "Accept: application/vnd.yang.data' \
+ '+xml" -H "Content-Type: application/vnd.yang.data+json" ' \
+ '-X POST -d "{{\\"enable\\":{start}}}" ' \
+ 'http://{mgmt_ip}:{mgmt_port}/api/v1/ping/adminstatus/state'. \
+ format(
+ mgmt_ip=mgmt_ip,
+ mgmt_port=mgmt_port,
+ start=start)
+
+ logger.debug("Executing cmd: %s", cmd)
+ proc = subprocess.run(cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ logger.debug("Process: {}".format(proc))
+
+ rc = proc.returncode
+
+ if rc == 0:
+ # Check if we got 200 OK
+ resp = proc.stdout.decode()
+ if 'HTTP/1.1 200 OK' not in resp:
+ self._log.error("Got error response: {}".format(resp))
+ rc = 1
+
+ return rc
+
+
+def main(argv=sys.argv[1:]):
+ try:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+ parser.add_argument("-q", "--quiet", dest="verbose", action="store_false")
+ args = parser.parse_args()
+
+ run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
+ if not os.path.exists(run_dir):
+ os.makedirs(run_dir)
+ log_file = "{}/ping_start_stop-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+
+ # logging.basicConfig(filename=log_file, level=logging.DEBUG)
+ logger = logging.getLogger('ping-start-stop')
+ logger.setLevel(logging.DEBUG)
+
+ fh = logging.FileHandler(log_file)
+ fh.setLevel(logging.DEBUG)
+
+ ch = logging.StreamHandler()
+ if args.verbose:
+ ch.setLevel(logging.DEBUG)
+ else:
+ ch.setLevel(logging.INFO)
+
+ # create formatter and add it to the handlers
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ fh.setFormatter(formatter)
+ ch.setFormatter(formatter)
+ logger.addHandler(fh)
+ logger.addHandler(ch)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+ try:
+ logger.debug("Input file: {}".format(args.yaml_cfg_file.name))
+ yaml_str = args.yaml_cfg_file.read()
+ yaml_cfg = yaml.load(yaml_str)
+ logger.debug("Input YAML: {}".format(yaml_cfg))
+
+ rc = ping_start_stop(yaml_cfg, logger)
+ logger.info("Return code: {}".format(rc))
+ sys.exit(rc)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/usr/bin/env python3
+
+############################################################################
+# Copyright 2016 RIFT.IO Inc #
+# #
+# 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 argparse
+import logging
+import os
+import subprocess
+import sys
+import time
+
+import yaml
+
+
+def pong_setup(yaml_cfg, logger):
+ '''Use curl to configure ping and set the ping rate'''
+
+ # Get the required and optional parameters
+ params = yaml_cfg['parameters']
+ mgmt_ip = params['mgmt_ip']
+ mgmt_port = 18889
+ if 'mgmt_port' in params:
+ mgmt_port = params['mgmt_port']
+ service_ip = params['service_ip']
+ service_port = 5555
+ if 'service_port' in params:
+ service_port = params['service_port']
+ rate = 1
+ if 'rate' in params:
+ rate = params['rate']
+
+ config_cmd = 'curl -D /dev/stdout -H "Accept: application/vnd.yang.data' \
+ '+xml" -H "Content-Type: application/vnd.yang.data+json" ' \
+ '-X POST -d "{{\\"ip\\":\\"{service_ip}\\", \\"port\\":{service_port}}}" ' \
+ 'http://{mgmt_ip}:{mgmt_port}/api/v1/pong/server'. \
+ format(
+ mgmt_ip=mgmt_ip,
+ mgmt_port=mgmt_port,
+ service_ip=service_ip,
+ service_port=service_port)
+
+ logger.debug("Executing cmd: %s", config_cmd)
+ count = 0
+ delay = 5
+ max_tries = 12
+ rc = 0
+
+ while True:
+ count += 1
+ proc = subprocess.run(config_cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ logger.debug("Process: {}".format(proc))
+
+ if proc.returncode == 0:
+ # Check if response is 200 OK
+ resp = proc.stdout.decode()
+ if 'HTTP/1.1 200 OK' in resp:
+ rc = 0
+ break
+ self._log.error("Got error response: {}".format(resp))
+ rc = 1
+ break
+
+ elif proc.returncode == 7:
+ # Connection timeout
+ if count >= max_tries:
+ self._log.error("Connect failed for {}. Failing".format(count))
+ rc = 7
+ break
+ # Try after delay
+ time.sleep(delay)
+
+ return rc
+
+
+def main(argv=sys.argv[1:]):
+ try:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+ parser.add_argument("-q", "--quiet", dest="verbose", action="store_false")
+ args = parser.parse_args()
+
+ run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
+ if not os.path.exists(run_dir):
+ os.makedirs(run_dir)
+ log_file = "{}/pong_setup-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+
+ # logging.basicConfig(filename=log_file, level=logging.DEBUG)
+ logger = logging.getLogger('pong-setup')
+ logger.setLevel(logging.DEBUG)
+
+ fh = logging.FileHandler(log_file)
+ fh.setLevel(logging.DEBUG)
+
+ ch = logging.StreamHandler()
+ if args.verbose:
+ ch.setLevel(logging.DEBUG)
+ else:
+ ch.setLevel(logging.INFO)
+
+ # create formatter and add it to the handlers
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ fh.setFormatter(formatter)
+ ch.setFormatter(formatter)
+ logger.addHandler(fh)
+ logger.addHandler(ch)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+ try:
+ logger.debug("Input file: {}".format(args.yaml_cfg_file.name))
+ yaml_str = args.yaml_cfg_file.read()
+ yaml_cfg = yaml.load(yaml_str)
+ logger.debug("Input YAML: {}".format(yaml_cfg))
+
+ rc = pong_setup(yaml_cfg, logger)
+ logger.info("Return code: {}".format(rc))
+ sys.exit(rc)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+#!/usr/bin/env python3
+
+############################################################################
+# Copyright 2016 RIFT.IO Inc #
+# #
+# 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 argparse
+import logging
+import os
+import subprocess
+import sys
+import time
+
+import yaml
+
+
+def pong_start_stop(yaml_cfg, logger):
+ '''Use curl to configure ping and set the ping rate'''
+
+ # Get the required and optional parameters
+ params = yaml_cfg['parameters']
+ mgmt_ip = params['mgmt_ip']
+ mgmt_port = 18889
+ if 'mgmt_port' in params:
+ mgmt_port = params['mgmt_port']
+ start = 'true'
+ if 'start' in params:
+ if not params['start']:
+ start = 'false'
+
+ cmd = 'curl -D /dev/stdout -H "Accept: application/vnd.yang.data' \
+ '+xml" -H "Content-Type: application/vnd.yang.data+json" ' \
+ '-X POST -d "{{\\"enable\\":{start}}}" ' \
+ 'http://{mgmt_ip}:{mgmt_port}/api/v1/pong/adminstatus/state'. \
+ format(
+ mgmt_ip=mgmt_ip,
+ mgmt_port=mgmt_port,
+ start=start)
+
+ logger.debug("Executing cmd: %s", cmd)
+ proc = subprocess.run(cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ logger.debug("Process: {}".format(proc))
+
+ rc = proc.returncode
+
+ if rc == 0:
+ # Check if we got 200 OK
+ resp = proc.stdout.decode()
+ if 'HTTP/1.1 200 OK' not in resp:
+ self._log.error("Got error response: {}".format(resp))
+ rc = 1
+
+ return rc
+
+
+def main(argv=sys.argv[1:]):
+ try:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+ parser.add_argument("-q", "--quiet", dest="verbose", action="store_false")
+ args = parser.parse_args()
+
+ run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
+ if not os.path.exists(run_dir):
+ os.makedirs(run_dir)
+ log_file = "{}/pong_start_stop-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+
+ # logging.basicConfig(filename=log_file, level=logging.DEBUG)
+ logger = logging.getLogger('pong-start-stop')
+ logger.setLevel(logging.DEBUG)
+
+ fh = logging.FileHandler(log_file)
+ fh.setLevel(logging.DEBUG)
+
+ ch = logging.StreamHandler()
+ if args.verbose:
+ ch.setLevel(logging.DEBUG)
+ else:
+ ch.setLevel(logging.INFO)
+
+ # create formatter and add it to the handlers
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ fh.setFormatter(formatter)
+ ch.setFormatter(formatter)
+ logger.addHandler(fh)
+ logger.addHandler(ch)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+ try:
+ logger.debug("Input file: {}".format(args.yaml_cfg_file.name))
+ yaml_str = args.yaml_cfg_file.read()
+ yaml_cfg = yaml.load(yaml_str)
+ logger.debug("Input YAML: {}".format(yaml_cfg))
+
+ rc = pong_start_stop(yaml_cfg, logger)
+ logger.info("Return code: {}".format(rc))
+ sys.exit(rc)
+
+ except Exception as e:
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
vnf_type=vnf_type)
logger.debug("Executing cmd: %s", curl_cmd)
- subprocess.check_call(curl_cmd, shell=True)
+ proc = subprocess.run(curl_cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ logger.debug("Process: {}".format(proc))
+
+ return proc.returncode
# Enable pong service first
for index, vnfr in yaml_cfg['vnfr'].items():
if 'pong_vnfd' in vnfr['name']:
vnf_type = 'pong'
port = 18889
- enable_service(vnfr['mgmt_ip_address'], port, vnf_type)
+ rc = enable_service(vnfr['mgmt_ip_address'], port, vnf_type)
+ if rc != 0:
+ logger.error("Enable service for pong failed: {}".
+ format(rc))
+ return rc
break
# Add a delay to provide pong port to come up
- time.sleep(0.1)
+ time.sleep(1)
# Enable ping service next
for index, vnfr in yaml_cfg['vnfr'].items():
if 'ping_vnfd' in vnfr['name']:
vnf_type = 'ping'
port = 18888
- enable_service(vnfr['mgmt_ip_address'], port, vnf_type)
+ rc = enable_service(vnfr['mgmt_ip_address'], port, vnf_type)
break
+ return rc
+
+
def main(argv=sys.argv[1:]):
try:
parser = argparse.ArgumentParser()
if not os.path.exists(run_dir):
os.makedirs(run_dir)
log_file = "{}/ping_pong_start_traffic-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
- logging.basicConfig(filename=log_file, level=logging.DEBUG)
- logger = logging.getLogger()
- except Exception as e:
- print("Exception in {}: {}".format(__file__, e))
- sys.exit(1)
+ # logging.basicConfig(filename=log_file, level=logging.DEBUG)
+ logger = logging.getLogger('ping-pong-start-traffic')
+ logger.setLevel(logging.DEBUG)
+
+ fh = logging.FileHandler(log_file)
+ fh.setLevel(logging.DEBUG)
- try:
ch = logging.StreamHandler()
if args.verbose:
ch.setLevel(logging.DEBUG)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ fh.setFormatter(formatter)
ch.setFormatter(formatter)
+ logger.addHandler(fh)
logger.addHandler(ch)
except Exception as e:
- logger.exception(e)
- raise e
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
try:
+ logger.debug("Input file: {}".format(args.yaml_cfg_file.name))
yaml_str = args.yaml_cfg_file.read()
- # logger.debug("Input YAML file:\n{}".format(yaml_str))
yaml_cfg = yaml.load(yaml_str)
logger.debug("Input YAML: {}".format(yaml_cfg))
- start_traffic(yaml_cfg, logger)
+ rc = start_traffic(yaml_cfg, logger)
+ logger.info("Return code: {}".format(rc))
+ sys.exit(rc)
except Exception as e:
- logger.exception(e)
- raise e
+ logger.exception("Exception in {}: {}".format(__file__, e))
+ sys.exit(1)
if __name__ == "__main__":
main()
import asyncio
import concurrent.futures
+import os
import re
+import shlex
import tempfile
import yaml
-import os
from gi.repository import (
RwDts as rwdts,
def riftca_log(self, name, level, log_str, *args):
getattr(self._log, level)('RiftCA:({}) {}'.format(name, log_str), *args)
-
+
@asyncio.coroutine
def notify_create_vnfr(self, agent_nsr, agent_vnfr):
"""
pass
@asyncio.coroutine
- def vnf_config_primitive(self, agent_nsr, agent_vnfr, primitive, output):
+ def _vnf_config_primitive(self, nsr_id, vnfr_id, primitive,
+ vnf_config=None):
+ '''
+ Pass vnf_config to avoid querying DTS each time
+ '''
+ self._log.debug("VNF config primitive {} for nsr {}, vnfr {}".
+ format(primitive.name, nsr_id, vnfr_id))
+
+ if vnf_config is None:
+ vnfr = yield from self.get_vnfr(vnfr_id)
+ if vnfr is None:
+ self._log.error("Unable to get VNFR {} through DTS".
+ format(vnfr_id))
+ return 1, "Unable to get VNFR {} through DTS".format(vnfr_id)
+
+ vnf_config = vnfr.vnf_configuration
+ self._log.debug("VNF config= %s", vnf_config.as_dict())
+
+ data = {}
+ script = None
+ found = False
+
+ configs = vnf_config.config_primitive
+ for config in configs:
+ if config.name == primitive.name:
+ found = True
+ self._log.debug("RiftCA: Found the config primitive %s",
+ config.name)
+
+ spt = config.user_defined_script
+ if spt is None:
+ self._log.error("RiftCA: VNFR {}, Did not find "
+ "script defined in config {}".
+ format(vnfr['name'], config.as_dict()))
+ return 1, "Did not find user defined script for " \
+ "config primitive {}".format(primitive.name)
+
+ spt = shlex.quote(spt.strip())
+ if spt[0] == '/':
+ script = spt
+ else:
+ script = os.path.join(self._rift_artif_dir,
+ 'launchpad/libs',
+ nsr_id,
+ 'scripts',
+ spt)
+ self._log.debug("Rift config agent: Checking for script "
+ "in %s", script)
+ if not os.path.exists(script):
+ self._log.debug("Rift config agent: Did not find "
+ "script %s", script)
+ script = os.path.join(self._rift_install_dir,
+ 'usr/bin', spt)
+ if not os.path.exists(script):
+ self._log.debug("Rift config agent: Did not find "
+ "script %s", script)
+ return 1, "Did not find user defined " \
+ "script {}".format(spt)
+
+ params = {}
+ for param in config.parameter:
+ val = None
+ for p in primitive.parameter:
+ if p.name == param.name:
+ val = p.value
+ break
+
+ if val is None:
+ val = param.default_value
+
+ if val:
+ val = self.convert_value(val, param.data_type)
+
+ params.update({param.name: val})
+
+ data['parameters'] = params
+ break
+
+ if not found:
+ msg = "Did not find the primitive {} in VNFR {}". \
+ format(primitive.name, vnfr.name)
+ self._log.error(msg)
+ return 1, msg
+
+ rc, script_err = yield from self.exec_script(script, data)
+ return rc, script_err
+
+ @asyncio.coroutine
+ def vnf_config_primitive(self, nsr_id, vnfr_id, primitive, output):
'''
primitives support by RiftCA
+
+ Pass vnf_config to avoid querying DTS each time
'''
- pass
-
+ output.execution_status = "failed"
+ output.execution_id = ''
+ output.execution_error_details = ''
+
+ try:
+ vnfr = self._rift_vnfs[vnfr_id].vnfr
+ except KeyError:
+ msg = "Did not find VNFR %s in RiftCA plugin", vnfr_id
+ self._log.error(msg)
+ output.execution_error_details = msg
+ return
+
+ rc, err = yield from self._vnf_config_primitive(nsr_id,
+ vnfr_id,
+ primitive)
+ if rc == 0:
+ output.execution_status = "completed"
+ else:
+ if isinstance(err, bytes):
+ err = err.decode()
+ output.execution_error_details = err
+
@asyncio.coroutine
def apply_config(self, config, nsr, vnfr, rpc_ip):
""" Notification on configuration of an NSR """
return task, err
+ @asyncio.coroutine
+ def apply_initial_config_new(self, agent_nsr, agent_vnfr):
+ self._log.debug("RiftCA: VNF initial config primitive for nsr {}, vnfr {}".
+ format(agent_nsr.name, agent_vnfr.name))
+
+ try:
+ vnfr = self._rift_vnfs[agent_vnfr.id].vnfr
+ except KeyError:
+ self._log.error("RiftCA: Did not find VNFR %s in RiftCA plugin",
+ agent_vnfr.name)
+ return False
+
+ class Primitive:
+ def __init__(self, name):
+ self.name = name
+ self.value = None
+ self.parameter = []
+
+ vnfr = yield from self.get_vnfr(agent_vnfr.id)
+ if vnfr is None:
+ msg = "Unable to get VNFR {} ({}) through DTS". \
+ format(agent_vnfr.id, agent_vnfr.name)
+ self._log.error(msg)
+ raise RuntimeError(msg)
+
+ vnf_config = vnfr.vnf_configuration
+ self._log.debug("VNFR %s config: %s", vnfr.name,
+ vnf_config.as_dict())
+
+ # Sort the primitive based on the sequence number
+ primitives = sorted(vnf_config.initial_config_primitive,
+ key=lambda k: k.seq)
+ if not primitives:
+ self._log.debug("VNFR {}: No initial-config-primitive specified".
+ format(vnfr.name))
+ return True
+
+ for primitive in primitives:
+ if primitive.config_primitive_ref:
+ # Reference to a primitive in config primitive
+ prim = Primitive(primitive.config_primitive_ref)
+ rc, err = yield from self._vnf_config_primitive(agent_nsr.id,
+ agent_vnfr.id,
+ prim,
+ vnf_config)
+ if rc != 0:
+ msg = "Error executing initial config primitive" \
+ " {} in VNFR {}: rc={}, stderr={}". \
+ format(prim.name, vnfr.name, rc, err)
+ self._log.error(msg)
+ return False
+
+ elif primitive.name:
+ msg = "Primitive {} definition in initial config " \
+ "primitive for VNFR {} not supported yet". \
+ format(primtive.name, vnfr.name)
+ self._log.error(msg)
+ raise NotImplementedError(msg)
+
+ return True
+
@asyncio.coroutine
def apply_initial_config(self, agent_nsr, agent_vnfr):
"""
agent_vnfr.set_to_configurable()
if agent_vnfr.is_configurable:
# apply initial config for the vnfr
+ # Keep the config-template based initial-config
rc = yield from self._events.apply_vnf_config(agent_vnfr.vnf_cfg)
+
+ # Check if the new method of initial-config-primitive is present
+ if rc:
+ rc = yield from self.apply_initial_config_new(agent_nsr, agent_vnfr)
+
else:
self._log.info("Rift config agent: VNF:%s/%s is not configurable yet!",
agent_nsr.name, agent_vnfr.name)
+
except Exception as e:
self._log.error("Rift config agent: Error on initial configuration to VNF:{}/{}, e {}"
.format(agent_nsr.name, agent_vnfr.name, str(e)))
-
+
self._log.exception(e)
- return rc
+ return False
return rc
import asyncio
import abc
+import os
+import tempfile
+import yaml
+
+import gi
+gi.require_version('RwDts', '1.0')
+from gi.repository import (
+ RwDts as rwdts,
+)
# Default config agent plugin type
DEFAULT_CAP_TYPE = "riftca"
+
+class XPaths(object):
+ @staticmethod
+ def nsr_opdata(k=None):
+ return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
+ ("[nsr:ns-instance-config-ref='{}']".format(k) if k is not None else ""))
+
+ @staticmethod
+ def nsd_msg(k=None):
+ return ("C,/nsd:nsd-catalog/nsd:nsd" +
+ "[nsd:id = '{}']".format(k) if k is not None else "")
+
+ @staticmethod
+ def vnfr_opdata(k=None):
+ return ("D,/vnfr:vnfr-catalog/vnfr:vnfr" +
+ ("[vnfr:id='{}']".format(k) if k is not None else ""))
+
+ @staticmethod
+ def nsr_config(k=None):
+ return ("C,/nsr:ns-instance-config/nsr:nsr[nsr:id='{}']".format(k) if k is not None else "")
+
+
class RiftCMnsr(object):
'''
Agent class for NSR
def vnfr_ids(self):
return self._vnfr_ids
+ def get_member_vnfr(self, member_index):
+ for vnfr in self._vnfrs:
+ if vnfr.member_vnf_index == member_index:
+ return vnfr
+
+
class RiftCMvnfr(object):
'''
Agent base class for VNFR processing
"""Get the status of the service"""
return None
+ # Helper functions
+
+ def convert_value(self, value, type_='STRING'):
+ if type_ == 'STRING':
+ return str(value)
+
+ if type_ == 'INTEGER':
+ return int(value)
+
+ if type_ == 'BOOLEAN':
+ return (value == 1) or (value.lower() == 'true')
+
+ return value
+
+ @asyncio.coroutine
+ def _read_dts(self, xpath, do_trace=False):
+ self._log.debug("_read_dts path = %s", xpath)
+ flags = rwdts.XactFlag.MERGE
+ res_iter = yield from self._dts.query_read(
+ xpath, flags=flags
+ )
+
+ results = []
+ try:
+ for i in res_iter:
+ result = yield from i
+ if result is not None:
+ results.append(result.result)
+ except:
+ pass
+
+ return results
+
+
+ @asyncio.coroutine
+ def get_xpath(self, xpath):
+ self._log.debug("Attempting to get xpath: {}".format(xpath))
+ resp = yield from self._read_dts(xpath, False)
+ if len(resp) > 0:
+ self._log.debug("Got DTS resp: {}".format(resp[0]))
+ return resp[0]
+ return None
+
+ @asyncio.coroutine
+ def get_nsr(self, id):
+ self._log.debug("Attempting to get NSR: %s", id)
+ nsrl = yield from self._read_dts(XPaths.nsr_opdata(id), False)
+ nsr = None
+ if len(nsrl) > 0:
+ nsr = nsrl[0].as_dict()
+ return nsr
+
+ @asyncio.coroutine
+ def get_nsr_config(self, id):
+ self._log.debug("Attempting to get config NSR: %s", id)
+ nsrl = yield from self._read_dts(XPaths.nsr_config(id), False)
+ nsr = None
+ if len(nsrl) > 0:
+ nsr = nsrl[0]
+ return nsr
+
+ @asyncio.coroutine
+ def get_vnfr(self, id):
+ self._log.debug("Attempting to get VNFR: %s", id)
+ vnfrl = yield from self._read_dts(XPaths.vnfr_opdata(id), do_trace=False)
+ vnfr_msg = None
+ if len(vnfrl) > 0:
+ vnfr_msg = vnfrl[0]
+ return vnfr_msg
+
+ @asyncio.coroutine
+ def exec_script(self, script, data):
+ """Execute a shell script with the data as yaml input file"""
+ self._log.debug("Execute script {} with data {}".
+ format(script, data))
+ tmp_file = None
+ with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
+ tmp_file.write(yaml.dump(data, default_flow_style=True)
+ .encode("UTF-8"))
+
+ cmd = "{} {}".format(script, tmp_file.name)
+ self._log.debug("Running the CMD: {}".format(cmd))
+
+ try:
+ proc = yield from asyncio.create_subprocess_shell(
+ cmd,
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE)
+ rc = yield from proc.wait()
+ script_out, script_err = yield from proc.communicate()
+
+ except Exception as e:
+ msg = "Script {} caused exception: {}". \
+ format(script, e)
+ self._log.exception(msg)
+ rc = 1
+ script_err = msg
+ script_out = ''
+
+ finally:
+ # Remove the tempfile created
+ try:
+ os.remove(tmp_file.name)
+ except OSError as e:
+ self._log.info("Error removing tempfile {}: {}".
+ format(tmp_file.name, e))
+
+ self._log.debug("Script {}: rc={}\nStdOut:{}\nStdErr:{}".
+ format(script, rc, script_out, script_err))
+
+ return rc, script_err
+
@asyncio.coroutine
def invoke(self, method, *args):
try:
# Initialize all handles that needs to be registered
for reg in self.reg_handles:
yield from reg.register()
-
+
@asyncio.coroutine
def register_cm_state_opdata(self):
if 'config_template' in vnf_config:
- vnf_cfg['cfg_template'] = '{}_{}_template.cfg'.format(nsr_obj.cfg_path_prefix, config_priority['configuration_type'])
- vnf_cfg['cfg_file'] = '{}.{}'.format(nsr_obj.cfg_path_prefix, get_cfg_file_extension(method, configuration_options))
+ vnf_cfg['cfg_template'] = '{}_{}_template.cfg'.format(nsr_obj.cfg_path_prefix,
+ config_priority['configuration_type'])
+ vnf_cfg['cfg_file'] = '{}.{}'.format(nsr_obj.cfg_path_prefix,
+ get_cfg_file_extension(method,
+ configuration_options))
vnf_cfg['xlate_script'] = os.path.join(self._parent.cfg_dir, 'xlate_cfg.py')
try:
# Now write this template into file
nsr_obj.populate_vm_state_from_vnf_cfg()
@asyncio.coroutine
- def resolve_xpath(self, xpath, name, vnfd):
- # For now, use DTS to resolve the path
- # TODO (pjoseph): Add better xpath support
+ def update_config_primitives(self, nsr_obj):
+
+ # Process all config-primitives in the member VNFs
+ for vnfr in nsr_obj.vnfrs:
+ vnfd = vnfr['vnf_cfg']['agent_vnfr'].vnfd
+
+ try:
+ prims = vnfd.vnf_configuration.config_primitive
+ if not prims:
+ self._log.debug("VNFR {} with VNFD {} has no config primitives defined".
+ format(vnfr.name, vnfd.name))
+ return
+ except AttributeError as e:
+ self._log.error("No config primitives found on VNFR {} ({})".
+ format(vnfr.name, vnfd.name))
+ cm_state = nsr_obj.find_vnfr_cm_state(vnfr['id'])
+ caps = cm_state['vnf_access_point']['capability']
+ deps = cm_state['vnf_access_point']['dependency']
+
+ vnf_configuration = vnfd.vnf_configuration.as_dict()
+ vnf_configuration['config_primitive'] = []
+ for prim in prims:
+ confp = prim.as_dict()
+ for param in confp['parameter']:
+ # First check the param in capabilities
+ found = False
+ for cap in caps:
+ if cap['name'] == param['name']:
+ param['default_value'] = cap['value']
+ param['read_only'] = True
+ break
+ if not found:
+ for dep in deps:
+ if dep['name'] == param['name']:
+ param['default_value'] = dep['value']
+ param['read_only'] = True
+ found = True
+ break
+ self._log.debug("Config primitive: {}".format(confp))
+ vnf_configuration['config_primitive'].append(confp)
+
+ cm_state['vnf_configuration'] = vnf_configuration
+
+ # Publish the updated config primitives for the VNFRs
+ yield from nsr_obj.publish_cm_state()
- xpath_prefix = "C,/vnfd:vnfd-catalog/vnfd[id='{}']/vnfap/capability/capability[name='{}']/xpath". \
- format(vnfd.id, name)
+ @asyncio.coroutine
+ def get_resolved_xpath(self, xpath, name, vnf_name, xpath_prefix):
+ # For now, use DTS to resolve the path
+ # TODO (pjoseph): Add better xpath support
+ dts_path = xpath
if xpath.startswith('../'):
prefix = xpath_prefix
xp = xpath
while xp.startswith('../'):
idx = prefix.rfind('/')
if idx == -1:
- raise ValueError("VNFD {}, Did not find the xpath specified: {}".
- format(vnfd.name, xpath))
+ raise ValueError("VNF {}, Did not find the xpath specified: {}".
+ format(vnf_name, xpath))
prefix = prefix[:idx]
xp = xp[3:]
- idx = xp.rfind('/')
- if idx = -1:
- raise ValueError("VNFD {}, xpath {} should point to an attribute".
- format(vnfd.name, xpath))
- attr = xp[idx+1:]
- dts_path = prefix + '/' + xp[:idx]
- self._log.error("DTS path: {}, attribute: {}".format(dts_path, attribute))
+ dts_path = prefix + '/' + xp
elif xpath.startswith('/'):
dts_path = 'C,' + xpath
elif xpath.startswith('C,/') or xpath.startswith('D,/'):
dts_path = xpath
else:
- self._log.error("Unknown xpath {} for capability {} in VNFD {}".
- format(xpath, name, vnfd.name))
- return None
+ self._log.error("Invalid xpath {} for capability {} in VNF {}".
+ format(xpath, name, vnf_name))
+ raise ValueError("XPath {} in capability {} for VNF {} is invalid".
+ format(xpath, name, vnf_name))
+ return dts_path
+
+ @asyncio.coroutine
+ def resolve_xpath(self, xpath, name, vnfd):
+ xpath_prefix = "C,/vnfd:vnfd-catalog/vnfd[id='{}']/vnfap/capability" \
+ "/capability[name='{}']/xpath". \
+ format(vnfd.id, name)
+
+ dts_path = yield from self.get_resolved_xpath(xpath, name,
+ vnfd.name, xpath_prefix)
+ idx = dts_path.rfind('/')
+ if idx == -1:
+ raise ValueError("VNFD {}, xpath {} should point to an attribute".
+ format(vnfd.name, xpath))
+ attr = dts_path[idx+1:]
+ dts_path = dts_path[:idx]
+ self._log.debug("DTS path: {}, attribute: {}".format(dts_path, attr))
resp = yield from self.cmdts_obj.get_xpath(dts_path)
- self._log.error("DTS response: {}".resp)
+ if resp is None:
+ raise ValueError("Xpath {} in capability {} for VNFD {} is not found".
+ format(xpath, name, vnfd.name))
+ self._log.debug("DTS response: {}".format(resp.as_dict()))
+
+ try:
+ val = getattr(resp, attr)
+ except AttributeError as e:
+ self._log.error("Did not find attribute : {}".format(attr))
+ try:
+ val = getattr(resp, attr.replace('-', '_'))
+ except AttributeError as e:
+ raise ValueError("Did not find attribute {} in XPath {} "
+ "for capability {} in VNF {}".
+ format(attr, dts_path, vnfd.name))
+
+ self._log.debug("XPath {}: {}".format(xpath, val))
+ return val
@asyncio.coroutine
- def process_vnf_access_point(self, nsr_obj):
- nsd = nsr_obj.agent_nsr.nsd
- vnfap_map = None
+ def resolve_attribute(self, attribute, name, vnfd, vnfr):
+ idx = attribute.rfind(',')
+ if idx == -1:
+ raise ValueError ("Invalid attribute {} for capability {} in "
+ "VNFD specified".
+ format(attribute, name, vnfd.name))
+ xpath = attribute[:idx].strip()
+ attr = attribute[idx+1:].strip()
+ self._log.debug("Attribute {}, {}".format(xpath, attr))
+ if xpath.startswith('C,/'):
+ raise ValueError("Attribute {} for capability {} in VNFD cannot "
+ "be a config".
+ format(attribute, name, vnfd.name))
+
+ xpath_prefix = "D,/vnfr:vnfr-catalog/vnfr[id='{}']/vnfap/capability" \
+ "/capability[name='{}']/attribute". \
+ format(vnfr['id'], name)
+ dts_path = yield from self.get_resolved_xpath(xpath, name,
+ vnfr['name'],
+ xpath_prefix)
+ self._log.debug("DTS query: {}".format(dts_path))
+
+ resp = yield from self.cmdts_obj.get_xpath(dts_path)
+ if resp is None:
+ raise ValueError("Attribute {} in capability {} for VNFD {} is " \
+ "not found".
+ format(xpath, name, vnfd.name))
+ self._log.debug("DTS response: {}".format(resp.as_dict()))
+
try:
- vnfap_map = nsd.vnfap_map
+ val = getattr(resp, attr)
except AttributeError as e:
- self._log.error("No vnfap map specified for nsr: {}".
- format(nsr_obj.nsr_name))
- return
+ self._log.debug("Did not find attribute {}".format(attr))
+ try:
+ val = getattr(resp, attr.replace('-', '_'))
+ except AttributeError as e:
+ raise ValueError("Did not find attribute {} in XPath {} "
+ "for capability {} in VNF {}".
+ format(attr, dts_path, vnfd.name))
- if not len(vnfap_map):
- self._log.error("No entries in vnfap map for nsr: {}".
- format(nsr_obj.nsr_name))
- return
+ self._log.debug("Attribute {}: {}".format(attribute, val))
+ return val
+
+ @asyncio.coroutine
+ def process_vnf_access_point(self, nsr_obj):
+ nsd = nsr_obj.agent_nsr.nsd
# Process all capabilities in all the member VNFs
for vnfr in nsr_obj.vnfrs:
vnfd = vnfr['vnf_cfg']['agent_vnfr'].vnfd
- self._log.error("VNFD: {}".format(vnfd.as_dict()))
+
try:
vnfap = vnfd.vnfap
except AttributeError as e:
- self._log.error("VNFR {} does not have VNF access point".
+ self._log.debug("VNFR {} does not have VNF access point".
format(vnfr.name))
continue
+ caps = []
try:
caps = vnfap.capability
except AttributeError as e:
- self._log.error("VNFR {} has no capabilities defined".
+ self._log.debug("VNFR {} has no capabilities defined".
format(vnfr.name))
- continue
# Get the cm state dict for this vnfr
cm_state = nsr_obj.find_vnfr_cm_state(vnfr['id'])
- cm_caps = cm_state['vnf_access_point']['capability']
+ cm_caps = []
for cap in caps:
- self._log.error("VNFR {}: capability {}".
+ self._log.debug("VNFR {}: capability {}".
format(vnfr['name'], cap.as_dict()))
- val = None
try:
val = cap.value
- self._log.error("Got value {}".format(val))
+ self._log.debug("Got value {}".format(val))
+ if val:
+ cm_caps.append({'name': cap.name, 'value': str(val)})
+ continue
except AttributeError as e:
pass
- if val is None:
- try:
- xpath = cap.xpath
- # resolve xpath
+ try:
+ xpath = cap.xpath
+ # resolve xpath
+ if xpath:
val = yield from self.resolve_xpath(xpath, cap.name, vnfd)
self._log.debug("Got xpath value: {}".format(val))
- except AttributeError as e:
- pass
+ cm_caps.append({'name': cap.name, 'value': str(val)})
+ continue
+ except AttributeError as e:
+ pass
+
+ try:
+ attribute = cap.attribute
+ # resolve attribute
+ if attribute:
+ val = yield from self.resolve_attribute(attribute, cap.name, vnfd, vnfr)
+ self._log.debug("Got attribute value: {}".format(val))
+ cm_caps.append({'name': cap.name, 'value': str(val)})
+ continue
+ except AttributeError as e:
+ pass
+
+ self._log.debug("VNF Capabilities: {}".format(cm_caps))
+ cm_state['vnf_access_point']['capability'] = cm_caps
+
+ try:
+ deps = vnfap.dependency
+ except AttributeError as e:
+ self._log.debug("VNFR {} has no dependencies defined".
+ format(vnfr.name))
+ continue
+
+ cm_deps = []
+ for dep in deps:
+ self._log.debug("VNFR{}: dependency {}".
+ format(vnfr['name'], dep.as_dict()))
+ cm_deps.append({'name': dep.name, 'mandatory': dep.mandatory})
+
+ self._log.debug("VNF Dependencies: {}".format(cm_deps))
+ cm_state['vnf_access_point']['dependency'] = cm_deps
+
+ # Publish all capabilities for the VNFRs
+ yield from nsr_obj.publish_cm_state()
+
+ vnfap_map = None
+ try:
+ vnfap_map = nsd.vnfap_map
+ except AttributeError as e:
+ self._log.debug("No vnfap map specified for nsr: {}".
+ format(nsr_obj.nsr_name))
+ return
+ if not len(vnfap_map):
+ self._log.info("No entries in vnfap map for nsr: {}".
+ format(nsr_obj.nsr_name))
+ return
+
+ for ap in vnfap_map:
+ cap_vnfr = nsr_obj.agent_nsr.get_member_vnfr(ap.capability.member_vnf_index)
+ cm_state = nsr_obj.find_vnfr_cm_state(cap_vnfr.id)
+ if cm_state is None:
+ raise ValueError("Capabilities are not defined for VNF member {} ({})".
+ format(ap.capability.member_vnf_index, cap_vnfr.name))
+ caps = cm_state['vnf_access_point']['capability']
+
+ cap_attr = ap.capability.capability_ref
+ val = None
+ for cap in caps:
+ if cap['name'] == cap_attr:
+ val = cap['value']
+ break
+
+ dep_vnfr = nsr_obj.agent_nsr.get_member_vnfr(ap.dependency.member_vnf_index)
+ dep_attr = ap.dependency.dependency_ref
+ cm_state = nsr_obj.find_vnfr_cm_state(dep_vnfr.id)
+ try:
+ cm_deps = cm_state['vnf_access_point']['dependency']
+ except KeyError as e:
+ raise ValueError("VNFR index {} ({}) has no dependencies defined".
+ format(ap.dependency.member_vnf_index, dep_vnfr['name']))
+
+ for i, item in enumerate(cm_deps):
+ if item['name'] == dep_attr:
+ item['value'] = str(val)
+ cm_deps[i] = item
+ self._log.debug("Dependency in VNFR {}: {}".
+ format(dep_vnfr.name, item))
+ break
+
+ # Publish resolved dependencies for the VNFRs
+ yield from nsr_obj.publish_cm_state()
+ yield from self.update_config_primitives(nsr_obj)
@asyncio.coroutine
def config_NSR(self, id):
# Find vnfr for this vnf_unique_name
if vnf_unique_name not in nsr_obj._vnfr_dict:
- self._log.error("NS (%s) - Can not find VNF to be configured: %s", nsr_obj.nsr_name, vnf_unique_name)
+ self._log.error("NS (%s) - Can not find VNF to be configured: %s",
+ nsr_obj.nsr_name, vnf_unique_name)
else:
# Save this unique VNF's config input parameters
nsr_obj.vnf_config_attributes_dict[vnf_unique_name] = vnf_config_attributes_dict
self._log.debug("Running the CMD: {}".format(cmd))
process = yield from asyncio. \
- create_subprocess_shell(cmd, loop=self._loop)
+ create_subprocess_shell(
+ cmd, loop=self._loop,
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE)
yield from process.wait()
if process.returncode:
+ script_out, script_err = yield from proc.communicate()
msg = "NSR {} initial config using {} failed with {}". \
format(nsr_name, script, process.returncode)
self._log.error(msg)
+ self._log.error("Script {} stderr: {}".
+ format(script, script_err))
raise InitialConfigError(msg)
else:
os.remove(inp_file)
self._cp_dict['rw_mgmt_ip'] = vnf_cfg['mgmt_ip_address']
self._cp_dict['rw_username'] = vnf_cfg['username']
self._cp_dict['rw_password'] = vnf_cfg['password']
- ############################################################
- # TBD - Need to lookup above 3 for a given VNF, not global #
- # Once we do that no need to dump below file again before #
- # each VNF configuration translation. #
- # This will require all existing config templates to be #
- # changed for above three tags to include member index #
- ############################################################
- try:
- nsr_obj = vnf_cfg['nsr_obj']
- # Generate config_config_attributes.yaml (For debug reference)
- with open(nsr_obj.xlate_dict_file, "w") as yf:
- yf.write(yaml.dump(nsr_obj._cp_dict, default_flow_style=False))
- except Exception as e:
- self._log.error("NS:(%s) failed to write nsr xlate tags file as (%s)", nsr_obj.nsr_name, str(e))
if 'cfg_template' in vnf_cfg:
- script_cmd = 'python3 {} -i {} -o {} -x "{}"'.format(vnf_cfg['xlate_script'], vnf_cfg['cfg_template'], vnf_cfg['cfg_file'], self.xlate_dict_file)
- self._log.debug("xlate script command (%s)", script_cmd)
- #xlate_msg = subprocess.check_output(script_cmd).decode('utf-8')
- xlate_msg = subprocess.check_output(script_cmd, shell=True).decode('utf-8')
- self._log.info("xlate script output (%s)", xlate_msg)
+ try:
+ nsr_obj = vnf_cfg['nsr_obj']
+ # Generate config_config_attributes.yaml (For debug reference)
+ with open(nsr_obj.xlate_dict_file, "w") as yf:
+ yf.write(yaml.dump(nsr_obj._cp_dict, default_flow_style=False))
+ except Exception as e:
+ self._log.error("NS:(%s) failed to write nsr xlate tags "
+ "file as (%s)", nsr_obj.nsr_name, str(e))
+
+ script_cmd = 'python3 {} -i {} -o {} -x "{}"'. \
+ format(vnf_cfg['xlate_script'],
+ vnf_cfg['cfg_template'],
+ vnf_cfg['cfg_file'],
+ self.xlate_dict_file)
+ self._log.debug("xlate script command (%s)", script_cmd)
+ xlate_msg = subprocess.check_output(script_cmd, shell=True).decode('utf-8')
+ self._log.info("xlate script output (%s)", xlate_msg)
+
except Exception as e:
vnf_cm_state['state'] = self.state_to_string(conmanY.RecordState.CFG_PROCESS_FAILED)
- self._log.error("Failed to execute translation script for VNF: %s with (%s)", log_this_vnf(vnf_cfg), str(e))
+ self._log.error("Failed to execute translation script for VNF: %s with (%s)",
+ log_this_vnf(vnf_cfg), str(e))
return
self._log.info("Applying config to VNF: %s = %s!", log_this_vnf(vnf_cfg), vnf_cfg)
@asyncio.coroutine
def get_xpath(self, xpath):
- self._log.debug("Attempting to get {}".format(xpath))
+ self._log.debug("Attempting to get xpath: {}".format(xpath))
resp = yield from self._read_dts(xpath, False)
- return resp
+ if len(resp) > 0:
+ self._log.debug("Got DTS resp: {}".format(resp[0]))
+ return resp[0]
+ return None
@asyncio.coroutine
def get_nsr(self, id):
def register(self):
yield from self.register_to_publish()
yield from self.register_for_nsr()
-
+
@asyncio.coroutine
def register_to_publish(self):
''' Register to DTS for publishing cm-state opdata '''
else:
log_vnf += "{}/".format(vnf_cfg[item])
return log_vnf
-
+
+
class ConfigManagerROifConnectionError(Exception):
pass
+
+
class ScriptError(Exception):
pass
def update_vnf_state(self, vnf_cfg, state):
nsr_obj = vnf_cfg['nsr_obj']
yield from nsr_obj.update_vnf_cm_state(vnf_cfg['vnfr'], state)
-
+
@asyncio.coroutine
def apply_vnf_config(self, vnf_cfg):
self._log.debug("apply_vnf_config VNF:{}"
.format(log_this_vnf(vnf_cfg)))
-
+
if vnf_cfg['config_delay']:
yield from self.update_vnf_state(vnf_cfg, conmanY.RecordState.CFG_DELAY)
yield from asyncio.sleep(vnf_cfg['config_delay'], loop=self._loop)
-
+
# See if we are still alive!
if vnf_cfg['nsr_obj'].being_deleted:
# Don't do anything, just return
self._log.info("VNF : %s is being deleted, skipping configuration!",
log_this_vnf(vnf_cfg))
return True
-
+
yield from self.update_vnf_state(vnf_cfg, conmanY.RecordState.CFG_SEND)
try:
if vnf_cfg['config_method'] == 'netconf':
yield from self.update_vnf_state(vnf_cfg, conmanY.RecordState.CFG_FAILED)
return True
- #Update VNF state
- yield from self.update_vnf_state(vnf_cfg, conmanY.RecordState.READY)
- self._log.info("Successfully applied configuration to VNF: %s",
+ self._log.info("Successfully applied config template to VNF: %s",
log_this_vnf(vnf_cfg))
+
except Exception as e:
self._log.error("Applying configuration(%s) file(%s) to VNF: %s failed as: %s",
vnf_cfg['config_method'],
vnf_cfg['cfg_file'],
log_this_vnf(vnf_cfg),
str(e))
- #raise
+ self._log.exception(e)
return False
return True
-
+
class ConfigManagerVNFscriptconf(object):
def __init__(self, log, loop, parent, vnf_cfg):
#@asyncio.coroutine
def apply_edit_cfg(self):
vnf_cfg = self._vnf_cfg
- self._log.debug("Attempting to apply scriptconf to VNF: %s", log_this_vnf(vnf_cfg))
+ self._log.debug("Attempting to apply scriptconf to VNF %s: %s", log_this_vnf(vnf_cfg), vnf_cfg)
+
+ if vnf_cfg['cfg_file'] is None or (vnf_cfg['cfg_file'] == 'None'):
+ self._log.debug("Config file for script not provided")
+ return
+
try:
st = os.stat(vnf_cfg['cfg_file'])
os.chmod(vnf_cfg['cfg_file'], st.st_mode | stat.S_IEXEC)
vnf_cfg = self._vnf_cfg
self._log.debug("Attempting to apply netconf to VNF: %s", log_this_vnf(vnf_cfg))
+ if vnf_cfg['cfg_file'] is None or (vnf_cfg['cfg_file'] == 'None'):
+ self._log.debug("Config file for Netconf not provided")
+ return
+
if self._manager is None:
self._log.error("Netconf is not connected to VNF: %s, aborting!", log_this_vnf(vnf_cfg))
return
self.dts.handle.set_state(next_state)
def on_vnfr_create(self, vnfr):
- if not self.monitor.nfvi_metrics_available(vnfr.cloud_account):
+ try:
+ acc = vnfr.cloud_account
+ except AttributeError as e:
+ self.log.warning("NFVI metrics not supported")
+ return
+
+ if not self.monitor.nfvi_metrics_available(acc):
msg = "NFVI metrics unavailable for {}"
- self.log.warning(msg.format(vnfr.cloud_account))
+ self.log.warning(msg.format(acc))
return
self.monitor.add_vnfr(vnfr)
self.loop.create_task(coro)
def on_vnfr_update(self, vnfr):
+ try:
+ acc = vnfr.cloud_account
+ except AttributeError as e:
+ self.log.warning("NFVI metrics not supported")
+ return
+
if not self.monitor.nfvi_metrics_available(vnfr.cloud_account):
msg = "NFVI metrics unavailable for {}"
self.log.warning(msg.format(vnfr.cloud_account))
return
try:
- nsrid = cm_nsr['id']
+ nsrid = cm_nsr.id
# Update the VNFRs' config status
- gen = []
- if 'cm_vnfr' in cm_nsr:
- gen = (vnfr for vnfr in cm_nsr['cm_vnfr']
- if vnfr['id'] in self.nsm._vnfrs)
+ gen = (vnfr for vnfr in cm_nsr.cm_vnfr
+ if vnfr.id in self.nsm._vnfrs)
for vnfr in gen:
- vnfrid = vnfr['id']
- new_status = ROConfigManager.map_config_status(vnfr['state'])
+ vnfrid = vnfr.id
+ new_status = ROConfigManager.map_config_status(vnfr.state)
self._log.debug("Updating config status of VNFR {} " \
"in NSR {} to {}({})".
format(vnfrid, nsrid, new_status,
- vnfr['state']))
+ vnfr.state))
yield from \
self.nsm.vnfrs[vnfrid].set_config_status(new_status)
+ yield from \
+ self.nsm.vnfrs[vnfrid].update_config_primitives(
+ vnfr.vnf_configuration)
+
# Update the NSR's config status
- new_status = ROConfigManager.map_config_status(cm_nsr['state'])
- self._log.info("Updating config status of NSR {} to {}({})".
- format(nsrid, new_status, cm_nsr['state']))
+ new_status = ROConfigManager.map_config_status(cm_nsr.state)
+ self._log.debug("Updating config status of NSR {} to {}({})".
+ format(nsrid, new_status, cm_nsr.state))
- # If terminate nsr request comes when NS instantiation is in 'Configuring state'; self.nsm.nsrs dict
- # is already empty when self.nsm.nsrs[nsrid].set_config_status gets executed. So adding a check here.
+ # If terminate nsr request comes when NS instantiation is in
+ # 'Configuring state'; self.nsm.nsrs dict is already empty when
+ # self.nsm.nsrs[nsrid].set_config_status gets executed. So adding a check here.
if nsrid in self.nsm.nsrs:
- yield from self.nsm.nsrs[nsrid].set_config_status(new_status, cm_nsr.get('state_details'))
+ yield from self.nsm.nsrs[nsrid].set_config_status(
+ new_status,
+ cm_nsr.state_details)
except Exception as e:
self._log.error("Failed to process cm-state for nsr {}: {}".
@asyncio.coroutine
def register(self):
""" Register for cm-state changes """
-
+
@asyncio.coroutine
def on_prepare(xact_info, query_action, ks_path, msg):
""" cm-state changed """
- #print("###>>> cm-state change ({}), msg_dict = {}".format(query_action, msg_dict))
self._log.debug("Received cm-state on_prepare (%s:%s:%s)",
query_action,
ks_path,
if (query_action == rwdts.QueryAction.UPDATE or
query_action == rwdts.QueryAction.CREATE):
# Update Each NSR/VNFR state
- msg_dict = msg.as_dict()
- yield from self.update_ns_cfg_state(msg_dict)
+ # msg_dict = msg.as_dict()
+ yield from self.update_ns_cfg_state(msg)
elif query_action == rwdts.QueryAction.DELETE:
- self._log.debug("DELETE action in on_prepare for cm-state, ignoring")
+ self._log.debug("DELETE action in on_prepare for cm-state, "
+ "ignoring")
else:
raise NotImplementedError(
"%s on cm-state is not supported",
xact_info.respond_xpath(rwdts.XactRspCode.ACK)
try:
- handler = rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare)
- self.dts_reg_hdl = yield from self._dts.register(self.cm_state_xpath,
- flags=rwdts.Flag.SUBSCRIBER,
- handler=handler)
+ handler = rift.tasklets.DTS.RegistrationHandler(
+ on_prepare=on_prepare)
+ self.dts_reg_hdl = yield from self._dts.register(
+ self.cm_state_xpath,
+ flags=rwdts.Flag.SUBSCRIBER,
+ handler=handler)
+
except Exception as e:
- self._log.error("Failed to register for cm-state changes as %s", str(e))
-
+ self._log.error("Failed to register for cm-state changes as %s",
+ str(e))
gi.require_version('RwTypes', '1.0')
gi.require_version('RwVlrYang', '1.0')
gi.require_version('RwVnfrYang', '1.0')
+gi.require_version('VnfdYang', '1.0')
from gi.repository import (
RwYang,
RwNsrYang,
RwsdnYang,
RwDts as rwdts,
RwTypes,
+ VnfdYang,
ProtobufC,
)
@property
def const_vnfr_msg(self):
""" VNFR message """
- return RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_ConstituentVnfrRef(vnfr_id=self.id,cloud_account=self.cloud_account_name,om_datacenter=self._om_datacenter_name)
+ return RwNsrYang.YangData_Nsr_NsInstanceOpdata_Nsr_ConstituentVnfrRef(
+ vnfr_id=self.id,
+ cloud_account=self.cloud_account_name,
+ om_datacenter=self._om_datacenter_name)
@property
def vnfd(self):
format(self.name, self.vnfr_msg))
yield from self._dts.query_update(
self.xpath,
- rwdts.XactFlag.TRACE,
+ rwdts.XactFlag.REPLACE,
self.vnfr_msg
)
return False
+ @asyncio.coroutine
+ def update_config_primitives(self, vnf_config):
+ # Update only after we are configured
+ if self._config_status == NsrYang.ConfigStates.INIT:
+ return
+
+ if not vnf_config.as_dict():
+ return
+
+ self._log.debug("Update VNFR {} config: {}".
+ format(self.name, vnf_config.as_dict()))
+
+ # Update config primitive
+ updated = False
+ for prim in self._vnfd.vnf_configuration.config_primitive:
+ for p in vnf_config.config_primitive:
+ if prim.name == p.name:
+ for param in prim.parameter:
+ for pa in p.parameter:
+ if pa.name == param.name:
+ if not param.default_value or \
+ (pa.default_value != param.default_value):
+ param.default_value = pa.default_value
+ updated = True
+ break
+ break
+
+ if updated:
+ self._log.debug("Updated VNFD {} config: {}".
+ format(self._vnfd.name,
+ self._vnfd.vnf_configuration))
+ self._vnfr_msg = self.create_vnfr_msg()
+
+ try:
+ yield from self.update_vnfm()
+ except Exception as e:
+ self._log.error("Exception updating VNFM with new config "
+ "primitive for VNFR {}: {}".
+ format(self.name, e))
+ self._log.exception(e)
+
@asyncio.coroutine
def instantiate(self, nsr):
""" Instantiate this VNFR"""
return vnfr_msg
+ @asyncio.coroutine
+ def update_config(self, msg, xact):
+ self._log.debug("VNFM vnf config: {}".
+ format(msg.vnf_configuration.as_dict()))
+ self._config_status = msg.config_status
+ self._vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.from_dict(
+ msg.as_dict())
+ self._log.debug("VNFR msg config: {}".
+ format(self.msg.vnf_configuration.as_dict()))
+ yield from self.publish(xact)
+
@property
def dashboard_url(self):
ip, cfg_port = self.mgmt_intf_info()
self._log.debug("VNFR {} update config status {} (current {})".
format(vnfr.name, msg.config_status, vnfr.config_status))
- # Update the config status and publish
- vnfr._config_status = msg.config_status
- yield from vnfr.publish(None)
+ # Update the config and publish
+ yield from vnfr.update_config(msg, xact_info)
else:
raise NotImplementedError(
handler=hdl,
flags=(rwdts.Flag.PUBLISHER |
rwdts.Flag.NO_PREP_READ |
- rwdts.Flag.CACHE |
rwdts.Flag.DATASTORE),)
@asyncio.coroutine
xact, path, msg)
@asyncio.coroutine
- def update(self, xact, path, msg):
+ def update(self, xact, path, msg, flags=rwdts.XactFlag.REPLACE):
"""
Update a VNFR record in DTS with path and message
"""
self._log.debug("Updating VNFR xact = %s, %s:%s",
xact, path, msg)
- self.regh.update_element(path, msg)
+ self.regh.update_element(path, msg, flags)
self._log.debug("Updated VNFR xact = %s, %s:%s",
xact, path, msg)