Remove config template from use in ping-pong
[osm/SO.git] / examples / ping_pong_ns / rift / mano / examples / ping_pong_nsd.py
1 #!/usr/bin/env python3
2
3 #
4 # Copyright 2016 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18
19
20 import argparse
21 import os
22 import shutil
23 import sys
24 import uuid
25
26 import gi
27 gi.require_version('RwYang', '1.0')
28 gi.require_version('RwVnfdYang', '1.0')
29 gi.require_version('VnfdYang', '1.0')
30 gi.require_version('RwNsdYang', '1.0')
31 gi.require_version('NsdYang', '1.0')
32
33
34 from gi.repository import (
35 RwNsdYang,
36 NsdYang,
37 RwVnfdYang,
38 VnfdYang,
39 RwYang,
40 )
41
42
43 try:
44 import rift.mano.config_data.config as config_data
45 except ImportError:
46 # Load modules from common which are not yet installed
47 path = os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "../../../common/python/rift/mano")
48 sys.path.append(path)
49
50 import config_data.config as config_data
51
52
53 NUM_PING_INSTANCES = 1
54 MAX_VNF_INSTANCES_PER_NS = 10
55 use_epa = False
56 aws = False
57 pingcount = NUM_PING_INSTANCES
58 use_ping_cloud_init_file = ""
59 use_pong_cloud_init_file = ""
60
61 PING_USERDATA_FILE = '''#cloud-config
62 password: fedora
63 chpasswd: { expire: False }
64 ssh_pwauth: True
65 runcmd:
66 - [ systemctl, daemon-reload ]
67 - [ systemctl, enable, ping.service ]
68 - [ systemctl, start, --no-block, ping.service ]
69 - [ ifup, eth1 ]
70 '''
71
72 PONG_USERDATA_FILE = '''#cloud-config
73 password: fedora
74 chpasswd: { expire: False }
75 ssh_pwauth: True
76 runcmd:
77 - [ systemctl, daemon-reload ]
78 - [ systemctl, enable, pong.service ]
79 - [ systemctl, start, --no-block, pong.service ]
80 - [ ifup, eth1 ]
81 '''
82
83
84 class UnknownVNFError(Exception):
85 pass
86
87
88 class ManoDescriptor(object):
89 def __init__(self, name):
90 self.name = name
91 self.descriptor = None
92
93 def write_to_file(self, module_list, outdir, output_format):
94 model = RwYang.Model.create_libncx()
95 for module in module_list:
96 model.load_module(module)
97
98 if output_format == 'json':
99 with open('%s/%s.json' % (outdir, self.name), "w") as fh:
100 fh.write(self.descriptor.to_json(model))
101 elif output_format.strip() == 'xml':
102 with open('%s/%s.xml' % (outdir, self.name), "w") as fh:
103 fh.write(self.descriptor.to_xml_v2(model))
104 elif output_format.strip() == 'yaml':
105 with open('%s/%s.yaml' % (outdir, self.name), "w") as fh:
106 fh.write(self.descriptor.to_yaml(model))
107 else:
108 raise Exception("Invalid output format for the descriptor")
109
110 def get_json(self, module_list):
111 model = RwYang.Model.create_libncx()
112 for module in module_list:
113 model.load_module(module)
114 print(self.descriptor.to_json(model))
115
116
117 class VirtualNetworkFunction(ManoDescriptor):
118 def __init__(self, name, instance_count=1):
119 self.vnfd_catalog = None
120 self.vnfd = None
121 self.instance_count = instance_count
122 self._placement_groups = []
123 self.use_vnf_init_conf = False
124 super(VirtualNetworkFunction, self).__init__(name)
125
126 def add_placement_group(self, group):
127 self._placement_groups.append(group)
128
129 def compose(self, image_name, cloud_init="", cloud_init_file="", endpoint=None, mon_params=[],
130 mon_port=8888, mgmt_port=8888, num_vlr_count=1, num_ivlr_count=1,
131 num_vms=1, image_md5sum=None, mano_ut=False):
132 self.descriptor = RwVnfdYang.YangData_Vnfd_VnfdCatalog()
133 self.id = str(uuid.uuid1())
134 vnfd = self.descriptor.vnfd.add()
135 vnfd.id = self.id
136 vnfd.name = self.name
137 vnfd.short_name = self.name
138 vnfd.vendor = 'RIFT.io'
139 vnfd.logo = 'rift_logo.png'
140 vnfd.description = 'This is an example RIFT.ware VNF'
141 vnfd.version = '1.0'
142
143 self.vnfd = vnfd
144
145 if mano_ut is True:
146 internal_vlds = []
147 for i in range(num_ivlr_count):
148 internal_vld = vnfd.internal_vld.add()
149 internal_vld.id = 'ivld%s' % i
150 internal_vld.name = 'fabric%s' % i
151 internal_vld.short_name = 'fabric%s' % i
152 internal_vld.description = 'Virtual link for internal fabric%s' % i
153 internal_vld.type_yang = 'ELAN'
154 internal_vlds.append(internal_vld)
155
156 for i in range(num_vlr_count):
157 cp = vnfd.connection_point.add()
158 cp.type_yang = 'VPORT'
159 cp.name = '%s/cp%d' % (self.name, i)
160
161 if endpoint is not None:
162 endp = VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd_HttpEndpoint(
163 path=endpoint, port=mon_port, polling_interval_secs=2
164 )
165 vnfd.http_endpoint.append(endp)
166
167 # Monitoring params
168 for monp_dict in mon_params:
169 monp = VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd_MonitoringParam.from_dict(monp_dict)
170 monp.http_endpoint_ref = endpoint
171 vnfd.monitoring_param.append(monp)
172
173 if 'pong_' in self.name:
174 self.add_pong_config()
175 else:
176 self.add_ping_config()
177
178 for i in range(num_vms):
179 # VDU Specification
180 vdu = vnfd.vdu.add()
181 vdu.id = 'iovdu_%s' % i
182 vdu.name = 'iovdu_%s' % i
183 vdu.count = 1
184 # vdu.mgmt_vpci = '0000:00:20.0'
185
186 # specify the VM flavor
187 if use_epa:
188 vdu.vm_flavor.vcpu_count = 4
189 vdu.vm_flavor.memory_mb = 1024
190 vdu.vm_flavor.storage_gb = 4
191 else:
192 vdu.vm_flavor.vcpu_count = 1
193 vdu.vm_flavor.memory_mb = 512
194 vdu.vm_flavor.storage_gb = 4
195
196 # Management interface
197 mgmt_intf = vnfd.mgmt_interface
198 mgmt_intf.vdu_id = vdu.id
199 mgmt_intf.port = mgmt_port
200 mgmt_intf.dashboard_params.path = endpoint
201 mgmt_intf.dashboard_params.port = mgmt_port
202
203 if cloud_init_file and len(cloud_init_file):
204 vdu.cloud_init_file = cloud_init_file
205 else:
206 vdu.cloud_init = cloud_init
207 if aws:
208 vdu.cloud_init += " - [ systemctl, restart, --no-block, elastic-network-interfaces.service ]\n"
209
210 # sepcify the guest EPA
211 if use_epa:
212 vdu.guest_epa.trusted_execution = False
213 vdu.guest_epa.mempage_size = 'LARGE'
214 vdu.guest_epa.cpu_pinning_policy = 'DEDICATED'
215 vdu.guest_epa.cpu_thread_pinning_policy = 'PREFER'
216 vdu.guest_epa.numa_node_policy.node_cnt = 2
217 vdu.guest_epa.numa_node_policy.mem_policy = 'STRICT'
218
219 node = vdu.guest_epa.numa_node_policy.node.add()
220 node.id = 0
221 node.memory_mb = 512
222 vcpu = node.vcpu.add()
223 vcpu.id = 0
224 vcpu = node.vcpu.add()
225 vcpu.id = 1
226
227 node = vdu.guest_epa.numa_node_policy.node.add()
228 node.id = 1
229 node.memory_mb = 512
230 vcpu = node.vcpu.add()
231 vcpu.id = 2
232 vcpu = node.vcpu.add()
233 vcpu.id = 3
234
235 # specify the vswitch EPA
236 vdu.vswitch_epa.ovs_acceleration = 'DISABLED'
237 vdu.vswitch_epa.ovs_offload = 'DISABLED'
238
239 # Specify the hypervisor EPA
240 vdu.hypervisor_epa.type_yang = 'PREFER_KVM'
241
242 # Specify the host EPA
243 # vdu.host_epa.cpu_model = 'PREFER_SANDYBRIDGE'
244 # vdu.host_epa.cpu_arch = 'PREFER_X86_64'
245 # vdu.host_epa.cpu_vendor = 'PREFER_INTEL'
246 # vdu.host_epa.cpu_socket_count = 2
247 # vdu.host_epa.cpu_core_count = 8
248 # vdu.host_epa.cpu_core_thread_count = 2
249 # vdu.host_epa.cpu_feature = ['PREFER_AES', 'REQUIRE_VME', 'PREFER_MMX','REQUIRE_SSE2']
250
251 if aws:
252 vdu.image = 'rift-ping-pong'
253 else:
254 vdu.image = image_name
255 if image_md5sum is not None:
256 vdu.image_checksum = image_md5sum
257
258 if mano_ut is True:
259 for i in range(num_ivlr_count):
260 internal_cp = vdu.internal_connection_point.add()
261 if vnfd.name.find("ping") >= 0:
262 cp_name = "ping"
263 else:
264 cp_name = "pong"
265 internal_cp.name = cp_name + "/icp{}".format(i)
266 internal_cp.id = cp_name + "/icp{}".format(i)
267 internal_cp.type_yang = 'VPORT'
268 ivld_cp = internal_vlds[i].internal_connection_point_ref.add()
269 ivld_cp.id_ref = internal_cp.id
270
271 internal_interface = vdu.internal_interface.add()
272 internal_interface.name = 'fab%d' % i
273 internal_interface.vdu_internal_connection_point_ref = internal_cp.id
274 internal_interface.virtual_interface.type_yang = 'VIRTIO'
275
276 # internal_interface.virtual_interface.vpci = '0000:00:1%d.0'%i
277
278 for i in range(num_vlr_count):
279 external_interface = vdu.external_interface.add()
280 external_interface.name = 'eth%d' % i
281 external_interface.vnfd_connection_point_ref = '%s/cp%d' % (self.name, i)
282 if use_epa:
283 external_interface.virtual_interface.type_yang = 'VIRTIO'
284 else:
285 external_interface.virtual_interface.type_yang = 'VIRTIO'
286 # external_interface.virtual_interface.vpci = '0000:00:2%d.0'%i
287
288 for group in self._placement_groups:
289 placement_group = vnfd.placement_groups.add()
290 placement_group.name = group.name
291 placement_group.requirement = group.requirement
292 placement_group.strategy = group.strategy
293 if group.vdu_list:
294 ### Add specific VDUs to placement group
295 for vdu in group.vdu_list:
296 member_vdu = placement_group.member_vdus.add()
297 member_vdu.member_vdu_ref = vdu.id
298 else:
299 ### Add all VDUs to placement group
300 for vdu in vnfd.vdu:
301 member_vdu = placement_group.member_vdus.add()
302 member_vdu.member_vdu_ref = vdu.id
303
304
305 def add_ping_config(self):
306 vnfd = self.descriptor.vnfd[0]
307 # Add vnf configuration
308 vnf_config = vnfd.vnf_configuration
309
310 # vnf_config.config_attributes.config_delay = 10
311
312 # Select "script" configuration
313 vnf_config.script.script_type = 'bash'
314
315 # Add initial config primitive
316 vnf_config.create_initial_config_primitive()
317 init_config = VnfdYang.InitialConfigPrimitive.from_dict(
318 {
319 "seq": 1,
320 "name": "Ping config",
321 "user_defined_script": "ping_initial_config.py",
322 }
323 )
324 vnf_config.initial_config_primitive.append(init_config)
325
326 def add_pong_config(self):
327 vnfd = self.descriptor.vnfd[0]
328 # Add vnf configuration
329 vnf_config = vnfd.vnf_configuration
330
331 # Select "script" configuration
332 vnf_config.script.script_type = 'bash'
333
334 # Add initial config primitive
335 vnf_config.create_initial_config_primitive()
336 init_config = VnfdYang.InitialConfigPrimitive.from_dict(
337 {
338 "seq": 1,
339 "name": "Pong config",
340 "user_defined_script": "pong_initial_config.py",
341 }
342 )
343 vnf_config.initial_config_primitive.append(init_config)
344
345 def write_to_file(self, outdir, output_format):
346 dirpath = "%s/%s" % (outdir, self.name)
347 if not os.path.exists(dirpath):
348 os.makedirs(dirpath)
349 super(VirtualNetworkFunction, self).write_to_file(['vnfd', 'rw-vnfd'],
350 dirpath,
351 output_format)
352 self.add_scripts(outdir)
353
354 def add_scripts(self, outdir):
355 script_dir = os.path.join(outdir, self.name, 'cloud_init')
356 try:
357 os.makedirs(script_dir)
358 except OSError:
359 if not os.path.isdir(script_dir):
360 raise
361
362 if 'ping' in self.name:
363 script_file = os.path.join(script_dir, 'ping_cloud_init.cfg')
364 cfg = PING_USERDATA_FILE
365 else:
366 script_file = os.path.join(script_dir, 'pong_cloud_init.cfg')
367 cfg = PONG_USERDATA_FILE
368
369 with open(script_file, "w") as f:
370 f.write("{}".format(cfg))
371
372 self.add_config_scripts(outdir)
373
374 # Copy the vnf_init_config script
375 if self.use_vnf_init_conf and ('ping' in self.name):
376 script_name = 'ping_set_rate.py'
377
378 src_path = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
379 script_src = os.path.join(src_path, script_name)
380 if not os.path.exists(script_src):
381 src_path = os.path.join(os.environ['RIFT_ROOT'],
382 'modules/core/mano/examples/ping_pong_ns/rift/mano/examples')
383 script_src = os.path.join(src_path, script_name)
384
385 dest_path = os.path.join(outdir, self.name, 'scripts')
386 os.makedirs(dest_path, exist_ok=True)
387
388 shutil.copy2(script_src, dest_path)
389
390 def add_config_scripts(self, outdir):
391 dest_path = os.path.join(outdir, self.name, 'scripts')
392 try:
393 os.makedirs(dest_path)
394 except OSError:
395 if not os.path.isdir(dest_path):
396 raise
397
398 if 'pong_' in self.name:
399 scripts = ['pong_initial_config.py']
400 else:
401 scripts = ['ping_initial_config.py']
402
403 for script_name in scripts:
404 src_path = os.path.dirname(os.path.abspath(
405 os.path.realpath(__file__)))
406 script_src = os.path.join(src_path, script_name)
407 if not os.path.exists(script_src):
408 src_path = os.path.join(os.environ['RIFT_ROOT'],
409 'modules/core/mano/examples/'
410 'ping_pong_ns/rift/mano/examples')
411 script_src = os.path.join(src_path, script_name)
412
413 shutil.copy2(script_src, dest_path)
414
415
416 class NetworkService(ManoDescriptor):
417 def __init__(self, name):
418 super(NetworkService, self).__init__(name)
419 self._scale_groups = []
420 self.vnfd_config = {}
421 self._placement_groups = []
422
423 def default_config(self, vnfd):
424 vnf_config = vnfd.vnfd.vnf_configuration
425
426 vnf_config.config_attributes.config_priority = 0
427 vnf_config.config_attributes.config_delay = 0
428
429 # Select "script" configuration
430 vnf_config.script.script_type = 'bash'
431 vnf_config.config_template = "#!/bin/bash"
432
433
434 def ns_config(self, nsd, vnfd_list, mano_ut):
435 # Used by scale group
436 if mano_ut:
437 nsd.service_primitive.add().from_dict(
438 {
439 "name": "ping config",
440 "user_defined_script": "{}".format(os.path.join(
441 os.environ['RIFT_ROOT'],
442 'modules/core/mano',
443 'examples/ping_pong_ns/rift/mano/examples',
444 'ping_config_ut.sh'))
445 })
446 else:
447 nsd.service_primitive.add().from_dict(
448 {
449 "name": "ping config",
450 "user_defined_script": "ping_config.py"
451 })
452
453 def ns_initial_config(self, nsd):
454 nsd.initial_config_primitive.add().from_dict(
455 {
456 "seq": 1,
457 "name": "start traffic",
458 "user_defined_script": "start_traffic.py",
459 "parameter": [
460 {
461 'name': 'userid',
462 'value': 'rift',
463 },
464 ],
465 }
466 )
467
468 def add_scale_group(self, scale_group):
469 self._scale_groups.append(scale_group)
470
471 def add_placement_group(self, placement_group):
472 self._placement_groups.append(placement_group)
473
474 def create_mon_params(self, vnfds):
475 NsdMonParam = NsdYang.YangData_Nsd_NsdCatalog_Nsd_MonitoringParam
476 param_id = 1
477 for vnfd_obj in vnfds:
478 for mon_param in vnfd_obj.vnfd.monitoring_param:
479 nsd_monp = NsdMonParam.from_dict({
480 'id': str(param_id),
481 'name': mon_param.name,
482 'aggregation_type': "AVERAGE",
483 'value_type': mon_param.value_type,
484 'vnfd_monitoring_param': [
485 {'vnfd_id_ref': vnfd_obj.vnfd.id,
486 'vnfd_monitoring_param_ref': mon_param.id}]
487 })
488
489 self.nsd.monitoring_param.append(nsd_monp)
490 param_id += 1
491
492
493
494
495 def compose(self, vnfd_list, cpgroup_list, mano_ut,
496 use_ns_init_conf=True,
497 use_vnf_init_conf=True,):
498
499 if mano_ut:
500 # Disable NS initial config primitive
501 use_ns_init_conf = False
502 use_vnf_init_conf = False
503
504 self.descriptor = RwNsdYang.YangData_Nsd_NsdCatalog()
505 self.id = str(uuid.uuid1())
506 nsd = self.descriptor.nsd.add()
507 self.nsd = nsd
508 nsd.id = self.id
509 nsd.name = self.name
510 nsd.short_name = self.name
511 nsd.vendor = 'RIFT.io'
512 nsd.logo = 'rift_logo.png'
513 nsd.description = 'Toy NS'
514 nsd.version = '1.0'
515 nsd.input_parameter_xpath.append(
516 NsdYang.YangData_Nsd_NsdCatalog_Nsd_InputParameterXpath(
517 xpath="/nsd:nsd-catalog/nsd:nsd/nsd:vendor",
518 )
519 )
520
521 ip_profile = nsd.ip_profiles.add()
522 ip_profile.name = "InterVNFLink"
523 ip_profile.description = "Inter VNF Link"
524 ip_profile.ip_profile_params.ip_version = "ipv4"
525 ip_profile.ip_profile_params.subnet_address = "31.31.31.0/24"
526 ip_profile.ip_profile_params.gateway_address = "31.31.31.210"
527
528 vld_id = 1
529 for cpgroup in cpgroup_list:
530 vld = nsd.vld.add()
531 vld.id = 'ping_pong_vld%s' % vld_id
532 vld_id += 1
533 vld.name = 'ping_pong_vld' # hard coded
534 vld.short_name = vld.name
535 vld.vendor = 'RIFT.io'
536 vld.description = 'Toy VL'
537 vld.version = '1.0'
538 vld.type_yang = 'ELAN'
539 vld.ip_profile_ref = 'InterVNFLink'
540 for cp in cpgroup:
541 cpref = vld.vnfd_connection_point_ref.add()
542 cpref.member_vnf_index_ref = cp[0]
543 cpref.vnfd_id_ref = cp[1]
544 cpref.vnfd_connection_point_ref = cp[2]
545
546 vnfd_index_map = {}
547 member_vnf_index = 1
548 for vnfd in vnfd_list:
549 for i in range(vnfd.instance_count):
550 constituent_vnfd = nsd.constituent_vnfd.add()
551 constituent_vnfd.member_vnf_index = member_vnf_index
552 vnfd_index_map[vnfd] = member_vnf_index
553
554 # Set the start by default to false for ping vnfd,
555 # if scaling is enabled
556 if (len(self._scale_groups) and
557 vnfd.descriptor.vnfd[0].name == 'ping_vnfd'):
558 constituent_vnfd.start_by_default = False
559
560 constituent_vnfd.vnfd_id_ref = vnfd.descriptor.vnfd[0].id
561 self.default_config(vnfd)
562 member_vnf_index += 1
563
564 # Enable config primitives if either mano_ut or
565 # scale groups are enabled
566 if mano_ut or len(self._scale_groups):
567 self.ns_config(nsd, vnfd_list, mano_ut)
568
569 # Add NS initial config to start traffic
570 if use_ns_init_conf:
571 self.ns_initial_config(nsd)
572
573 for scale_group in self._scale_groups:
574 group_desc = nsd.scaling_group_descriptor.add()
575 group_desc.name = scale_group.name
576 group_desc.max_instance_count = scale_group.max_count
577 group_desc.min_instance_count = scale_group.min_count
578 for vnfd, count in scale_group.vnfd_count_map.items():
579 member = group_desc.vnfd_member.add()
580 member.member_vnf_index_ref = vnfd_index_map[vnfd]
581 member.count = count
582
583 for trigger in scale_group.config_action:
584 config_action = group_desc.scaling_config_action.add()
585 config_action.trigger = trigger
586 config = scale_group.config_action[trigger]
587 config_action.ns_config_primitive_name_ref = config['ns-config-primitive-name-ref']
588
589 for placement_group in self._placement_groups:
590 group = nsd.placement_groups.add()
591 group.name = placement_group.name
592 group.strategy = placement_group.strategy
593 group.requirement = placement_group.requirement
594 for member_vnfd in placement_group.vnfd_list:
595 member = group.member_vnfd.add()
596 member.vnfd_id_ref = member_vnfd.descriptor.vnfd[0].id
597 member.member_vnf_index_ref = vnfd_index_map[member_vnfd]
598
599 # self.create_mon_params(vnfd_list)
600
601 def write_config(self, outdir, vnfds):
602
603 converter = config_data.ConfigPrimitiveConvertor()
604 yaml_data = converter.extract_nsd_config(self.nsd)
605
606 ns_config_dir = os.path.join(outdir, self.name, "ns_config")
607 os.makedirs(ns_config_dir, exist_ok=True)
608 vnf_config_dir = os.path.join(outdir, self.name, "vnf_config")
609 os.makedirs(vnf_config_dir, exist_ok=True)
610
611 if len(yaml_data):
612 with open('%s/%s.yaml' % (ns_config_dir, self.id), "w") as fh:
613 fh.write(yaml_data)
614
615 for i, vnfd in enumerate(vnfds, start=1):
616 yaml_data = converter.extract_vnfd_config(vnfd)
617
618 if len(yaml_data):
619 with open('%s/%s__%s.yaml' % (vnf_config_dir, vnfd.id, i), "w") as fh:
620 fh.write(yaml_data)
621
622 def write_initial_config_script(self, outdir):
623 script_name = 'start_traffic.py'
624
625 src_path = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
626 script_src = os.path.join(src_path, script_name)
627 if not os.path.exists(script_src):
628 src_path = os.path.join(os.environ['RIFT_ROOT'],
629 'modules/core/mano/examples/ping_pong_ns/rift/mano/examples')
630 script_src = os.path.join(src_path, script_name)
631
632 dest_path = os.path.join(outdir, 'scripts')
633 os.makedirs(dest_path, exist_ok=True)
634
635 shutil.copy2(script_src, dest_path)
636
637 def write_to_file(self, outdir, output_format):
638 dirpath = os.path.join(outdir, self.name)
639 if not os.path.exists(dirpath):
640 os.makedirs(dirpath)
641
642 super(NetworkService, self).write_to_file(["nsd", "rw-nsd"],
643 dirpath,
644 output_format)
645
646 # Write the initial config script
647 self.write_initial_config_script(dirpath)
648
649
650 def get_ping_mon_params(path):
651 return [
652 {
653 'id': '1',
654 'name': 'ping-request-tx-count',
655 'http_endpoint_ref': path,
656 'json_query_method': "NAMEKEY",
657 'value_type': "INT",
658 'description': 'no of ping requests',
659 'group_tag': 'Group1',
660 'widget_type': 'COUNTER',
661 'units': 'packets'
662 },
663
664 {
665 'id': '2',
666 'name': 'ping-response-rx-count',
667 'http_endpoint_ref': path,
668 'json_query_method': "NAMEKEY",
669 'value_type': "INT",
670 'description': 'no of ping responses',
671 'group_tag': 'Group1',
672 'widget_type': 'COUNTER',
673 'units': 'packets'
674 },
675 ]
676
677
678 def get_pong_mon_params(path):
679 return [
680 {
681 'id': '1',
682 'name': 'ping-request-rx-count',
683 'http_endpoint_ref': path,
684 'json_query_method': "NAMEKEY",
685 'value_type': "INT",
686 'description': 'no of ping requests',
687 'group_tag': 'Group1',
688 'widget_type': 'COUNTER',
689 'units': 'packets'
690 },
691
692 {
693 'id': '2',
694 'name': 'ping-response-tx-count',
695 'http_endpoint_ref': path,
696 'json_query_method': "NAMEKEY",
697 'value_type': "INT",
698 'description': 'no of ping responses',
699 'group_tag': 'Group1',
700 'widget_type': 'COUNTER',
701 'units': 'packets'
702 },
703 ]
704
705
706 class ScaleGroup(object):
707 def __init__(self, name, min_count=1, max_count=1):
708 self.name = name
709 self.min_count = min_count
710 self.max_count = max_count
711 self.vnfd_count_map = {}
712 self.config_action = {}
713
714 def add_vnfd(self, vnfd, vnfd_count):
715 self.vnfd_count_map[vnfd] = vnfd_count
716
717 def add_config(self):
718 self.config_action['post_scale_out']= {'ns-config-primitive-name-ref':
719 'ping config'}
720
721 class PlacementGroup(object):
722 def __init__(self, name):
723 self.name = name
724 self.strategy = ''
725 self.requirement = ''
726
727 def add_strategy(self, strategy):
728 self.strategy = strategy
729
730 def add_requirement(self, requirement):
731 self.requirement = requirement
732
733 class NsdPlacementGroup(PlacementGroup):
734 def __init__(self, name):
735 self.vnfd_list = []
736 super(NsdPlacementGroup, self).__init__(name)
737
738 def add_member(self, vnfd):
739 self.vnfd_list.append(vnfd)
740
741
742 class VnfdPlacementGroup(PlacementGroup):
743 def __init__(self, name):
744 self.vdu_list = []
745 super(VnfdPlacementGroup, self).__init__(name)
746
747 def add_member(self, vdu):
748 self.vdu_list.append(vdu)
749
750
751
752
753 def generate_ping_pong_descriptors(fmt="json",
754 write_to_file=False,
755 out_dir="./",
756 pingcount=NUM_PING_INSTANCES,
757 external_vlr_count=1,
758 internal_vlr_count=1,
759 num_vnf_vms=1,
760 ping_md5sum=None,
761 pong_md5sum=None,
762 mano_ut=False,
763 use_scale_group=False,
764 ping_fmt=None,
765 pong_fmt=None,
766 nsd_fmt=None,
767 use_mon_params=True,
768 ping_userdata=None,
769 pong_userdata=None,
770 ex_ping_userdata=None,
771 ex_pong_userdata=None,
772 use_placement_group=True,
773 use_ns_init_conf=True,
774 use_vnf_init_conf=True,
775 ):
776 # List of connection point groups
777 # Each connection point group refers to a virtual link
778 # the CP group consists of tuples of connection points
779 cpgroup_list = []
780 for i in range(external_vlr_count):
781 cpgroup_list.append([])
782
783 suffix = ''
784 ping = VirtualNetworkFunction("ping_vnfd%s" % (suffix), pingcount)
785 ping.use_vnf_init_conf = use_vnf_init_conf
786
787 if use_placement_group:
788 ### Add group name Eris
789 group = VnfdPlacementGroup('Eris')
790 group.add_strategy('COLOCATION')
791 group.add_requirement('''Place this VM on the Kuiper belt object Eris''')
792 ping.add_placement_group(group)
793
794 # ping = VirtualNetworkFunction("ping_vnfd", pingcount)
795 if not ping_userdata:
796 ping_userdata = PING_USERDATA_FILE
797
798 if ex_ping_userdata:
799 ping_userdata = '''\
800 {ping_userdata}
801 {ex_ping_userdata}
802 '''.format(
803 ping_userdata=ping_userdata,
804 ex_ping_userdata=ex_ping_userdata
805 )
806
807 ping.compose(
808 "Fedora-x86_64-20-20131211.1-sda-ping.qcow2",
809 ping_userdata,
810 use_ping_cloud_init_file,
811 "api/v1/ping/stats",
812 get_ping_mon_params("api/v1/ping/stats") if use_mon_params else [],
813 mon_port=18888,
814 mgmt_port=18888,
815 num_vlr_count=external_vlr_count,
816 num_ivlr_count=internal_vlr_count,
817 num_vms=num_vnf_vms,
818 image_md5sum=ping_md5sum,
819 mano_ut=mano_ut,
820 )
821
822 pong = VirtualNetworkFunction("pong_vnfd%s" % (suffix))
823
824 if use_placement_group:
825 ### Add group name Weywot
826 group = VnfdPlacementGroup('Weywot')
827 group.add_strategy('COLOCATION')
828 group.add_requirement('''Place this VM on the Kuiper belt object Weywot''')
829 pong.add_placement_group(group)
830
831
832 # pong = VirtualNetworkFunction("pong_vnfd")
833
834 if not pong_userdata:
835 pong_userdata = PONG_USERDATA_FILE
836
837 if ex_pong_userdata:
838 pong_userdata = '''\
839 {pong_userdata}
840 {ex_pong_userdata}
841 '''.format(
842 pong_userdata=pong_userdata,
843 ex_pong_userdata=ex_pong_userdata
844 )
845
846
847 pong.compose(
848 "Fedora-x86_64-20-20131211.1-sda-pong.qcow2",
849 pong_userdata,
850 use_pong_cloud_init_file,
851 "api/v1/pong/stats",
852 get_pong_mon_params("api/v1/pong/stats") if use_mon_params else [],
853 mon_port=18889,
854 mgmt_port=18889,
855 num_vlr_count=external_vlr_count,
856 num_ivlr_count=internal_vlr_count,
857 num_vms=num_vnf_vms,
858 image_md5sum=pong_md5sum,
859 mano_ut=mano_ut,
860 )
861
862 # Initialize the member VNF index
863 member_vnf_index = 1
864
865 # define the connection point groups
866 for index, cp_group in enumerate(cpgroup_list):
867 desc_id = ping.descriptor.vnfd[0].id
868 filename = 'ping_vnfd{}/cp{}'.format(suffix, index)
869
870 for idx in range(pingcount):
871 cp_group.append((
872 member_vnf_index,
873 desc_id,
874 filename,
875 ))
876
877 member_vnf_index += 1
878
879 desc_id = pong.descriptor.vnfd[0].id
880 filename = 'pong_vnfd{}/cp{}'.format(suffix, index)
881
882 cp_group.append((
883 member_vnf_index,
884 desc_id,
885 filename,
886 ))
887
888 member_vnf_index += 1
889
890 vnfd_list = [ping, pong]
891
892 nsd_catalog = NetworkService("ping_pong_nsd%s" % (suffix))
893
894 if use_scale_group:
895 group = ScaleGroup("ping_group", max_count=10)
896 group.add_vnfd(ping, 1)
897 group.add_config()
898 nsd_catalog.add_scale_group(group)
899
900 if use_placement_group:
901 ### Add group name Orcus
902 group = NsdPlacementGroup('Orcus')
903 group.add_strategy('COLOCATION')
904 group.add_requirement('''Place this VM on the Kuiper belt object Orcus''')
905
906 for member_vnfd in vnfd_list:
907 group.add_member(member_vnfd)
908
909 nsd_catalog.add_placement_group(group)
910
911 ### Add group name Quaoar
912 group = NsdPlacementGroup('Quaoar')
913 group.add_strategy('COLOCATION')
914 group.add_requirement('''Place this VM on the Kuiper belt object Quaoar''')
915
916 for member_vnfd in vnfd_list:
917 group.add_member(member_vnfd)
918
919 nsd_catalog.add_placement_group(group)
920
921
922 nsd_catalog.compose(vnfd_list,
923 cpgroup_list,
924 mano_ut,
925 use_ns_init_conf=use_ns_init_conf,
926 use_vnf_init_conf=use_vnf_init_conf,)
927
928 if write_to_file:
929 ping.write_to_file(out_dir, ping_fmt if ping_fmt is not None else fmt)
930 pong.write_to_file(out_dir, pong_fmt if ping_fmt is not None else fmt)
931 nsd_catalog.write_config(out_dir, vnfd_list)
932 nsd_catalog.write_to_file(out_dir, ping_fmt if nsd_fmt is not None else fmt)
933
934 return (ping, pong, nsd_catalog)
935
936
937 def main(argv=sys.argv[1:]):
938 global outdir, output_format, use_epa, aws, use_ping_cloud_init_file, use_pong_cloud_init_file
939 parser = argparse.ArgumentParser()
940 parser.add_argument('-o', '--outdir', default='.')
941 parser.add_argument('-f', '--format', default='json')
942 parser.add_argument('-e', '--epa', action="store_true", default=False)
943 parser.add_argument('-a', '--aws', action="store_true", default=False)
944 parser.add_argument('-n', '--pingcount', default=NUM_PING_INSTANCES)
945 parser.add_argument('--ping-image-md5')
946 parser.add_argument('--pong-image-md5')
947 parser.add_argument('--ping-cloud-init', default=None)
948 parser.add_argument('--pong-cloud-init', default=None)
949 args = parser.parse_args()
950 outdir = args.outdir
951 output_format = args.format
952 use_epa = args.epa
953 aws = args.aws
954 pingcount = args.pingcount
955 use_ping_cloud_init_file = args.ping_cloud_init
956 use_pong_cloud_init_file = args.pong_cloud_init
957
958 generate_ping_pong_descriptors(args.format, True, args.outdir, pingcount,
959 ping_md5sum=args.ping_image_md5, pong_md5sum=args.pong_image_md5,
960 mano_ut=False,
961 use_scale_group=False,)
962
963 if __name__ == "__main__":
964 main()