3 # Copyright 2016 RIFT.IO Inc
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
19 @author Varun Prasad (varun.prasad@riftio.com)
27 import multiprocessing
37 from gi
import require_version
38 require_version('RwCal', '1.0')
40 from gi
.repository
import RwcalYang
41 from gi
.repository
.RwTypes
import RwStatus
42 # import rift.cal.server as cal_server
47 logger
= logging
.getLogger('rwcal')
48 logging
.basicConfig(level
=logging
.INFO
)
51 return uuid
.uuid4().hex[:10]
53 class CloudConfig(object):
54 def __init__(self
, cal
, account
):
56 self
.account
= account
58 def check_state(self
, object_id
, object_api
, expected_state
, state_attr_name
="state"):
59 """For a given object (Vm, port etc) checks if the object has
60 reached the expected state.
62 get_object
= getattr(self
.cal
, object_api
)
63 for i
in range(100): # 100 poll iterations...
64 rc
, rs
= get_object(self
.account
, object_id
)
66 curr_state
= getattr(rs
, state_attr_name
)
67 if curr_state
== expected_state
:
72 rc
, rs
= get_object(self
.account
, object_id
)
73 assert rc
== RwStatus
.SUCCESS
74 assert getattr(rs
, state_attr_name
) == expected_state
76 def start_server(self
):
79 def stop_server(self
):
87 def _account(self
, option
):
103 def virtual_link(self
):
107 class Aws(CloudConfig
):
108 def __init__(self
, option
):
111 option (OptionParser): OptionParser instance.
113 self
.image_id
= 'ami-7070231a'
114 self
.virtual_link_id
= None
115 self
.flavor_id
= None
118 super().__init
__(self
._cal
(), self
._account
(option
))
122 Loads rw.cal plugin via libpeas
124 plugin
= rw_peas
.PeasPlugin('rwcal_aws', 'RwCal-1.0')
126 engine
, info
, extension
= plugin()
128 # Get the RwLogger context
129 rwloggerctx
= rwlogger
.RwLog
.Ctx
.new("Cal-Log")
131 cal
= plugin
.get_interface("Cloud")
133 rc
= cal
.init(rwloggerctx
)
134 assert rc
== RwStatus
.SUCCESS
136 logger
.error("ERROR:Cal plugin instantiation failed. Aborting tests")
138 logger
.info("AWS Cal plugin successfully instantiated")
141 def _account(self
, option
):
144 option (OptionParser): OptionParser instance.
149 account
= RwcalYang
.YangData_RwProject_Project_CloudAccounts_CloudAccountList
.from_dict({
150 "account_type": "aws",
152 "key": option
.aws_user
,
153 "secret": option
.aws_password
,
154 "region": option
.aws_region
,
155 "availability_zone": option
.aws_zone
,
156 "ssh_key": option
.aws_ssh_key
167 flavor
= RwcalYang
.YangData_RwProject_Project_VimResources_FlavorinfoList
.from_dict({
168 "name": rift
.auto
.mano
.resource_name(short_id()),
179 """Provide AWS specific VDU config.
184 vdu
= RwcalYang
.YangData_RwProject_Project_VduInitParams
.from_dict({
185 "name": rift
.auto
.mano
.resource_name(short_id()),
186 "node_id": "123456789012345",
187 "image_id": self
.image_id
,
188 "flavor_id": "t2.micro"
191 c1
= vdu
.connection_points
.add()
192 c1
.name
= rift
.auto
.mano
.resource_name(short_id())
193 c1
.virtual_link_id
= self
.virtual_link_id
198 raise NotImplementedError("Image create APIs are not implemented for AWS")
200 def virtual_link(self
):
201 """Provide Vlink config
206 vlink
= RwcalYang
.YangData_RwProject_Project_VirtualLinkReqParams
.from_dict({
207 "name": rift
.auto
.mano
.resource_name(short_id()),
208 "subnet": '172.31.64.0/20',
214 class Cloudsim(CloudConfig
):
215 def __init__(self
, option
):
217 self
.virtual_link_id
= None
218 self
.flavor_id
= None
221 self
.server_process
= None
224 super().__init
__(self
._cal
(), self
._account
(option
))
226 def _md5(fname
, blksize
=1048576):
227 hash_md5
= hashlib
.md5()
228 with
open(fname
, "rb") as f
:
229 for chunk
in iter(lambda: f
.read(blksize
), b
""):
230 hash_md5
.update(chunk
)
231 return hash_md5
.hexdigest()
233 def start_server(self
):
234 logger
= logging
.getLogger(__name__
)
235 server
= cal_server
.CloudsimServerOperations(logger
)
236 self
.server_process
= multiprocessing
.Process(
237 target
=server
.start_server
,
239 self
.server_process
.start()
241 # Sleep till the backup store is set up
244 def stop_server(self
):
245 self
.server_process
.terminate()
247 # If the process is not killed within the timeout, send a SIGKILL.
249 if self
.server_process
.is_alive():
250 os
.kill(self
.server_process
.pid
, signal
.SIGKILL
)
254 Loads rw.cal plugin via libpeas
256 plugin
= rw_peas
.PeasPlugin('rwcal_cloudsimproxy', 'RwCal-1.0')
257 engine
, info
, extension
= plugin()
259 # Get the RwLogger context
260 rwloggerctx
= rwlogger
.RwLog
.Ctx
.new("Cal-Log")
262 cal
= plugin
.get_interface("Cloud")
264 rc
= cal
.init(rwloggerctx
)
265 assert rc
== RwStatus
.SUCCESS
267 logger
.error("ERROR:Cal plugin instantiation failed. Aborting tests")
269 logger
.info("Cloudsim Cal plugin successfully instantiated")
272 def _account(self
, option
):
275 option (OptionParser): OptionParser instance.
280 account
= RwcalYang
.YangData_RwProject_Project_CloudAccounts_CloudAccountList
.from_dict({
282 'account_type':'cloudsim_proxy'})
287 """Provides Image config for openstack.
292 image
= RwcalYang
.YangData_RwProject_Project_VimResources_ImageinfoList
.from_dict({
293 "name": rift
.auto
.mano
.resource_name(short_id()),
294 "location": os
.path
.join(os
.getenv("RIFT_ROOT"), "images/rift-root-latest.qcow2"),
295 "disk_format": "qcow2",
296 "container_format": "bare",
297 "checksum": self
._md
5(os
.path
.join(os
.getenv("RIFT_ROOT"), "images/rift-root-latest.qcow2")),
302 """Flavor config for openstack
307 flavor
= RwcalYang
.YangData_RwProject_Project_VimResources_FlavorinfoList
.from_dict({
308 "name": rift
.auto
.mano
.resource_name(short_id()),
318 """Returns VDU config
323 vdu
= RwcalYang
.YangData_RwProject_Project_VduInitParams
.from_dict({
324 "name": rift
.auto
.mano
.resource_name(short_id()),
325 "node_id": "123456789012345",
326 "image_id": self
.image_id
,
327 "flavor_id": self
.flavor_id
,
330 c1
= vdu
.connection_points
.add()
331 c1
.name
= rift
.auto
.mano
.resource_name(short_id())
332 c1
.virtual_link_id
= self
.virtual_link_id
336 def virtual_link(self
):
337 """vlink config for Openstack
342 vlink
= RwcalYang
.YangData_RwProject_Project_VirtualLinkReqParams
.from_dict({
343 "name": rift
.auto
.mano
.resource_name(short_id()),
344 "subnet": '192.168.1.0/24',
350 class Openstack(CloudConfig
):
351 def __init__(self
, option
):
354 option (OptionParser)
357 self
.virtual_link_id
= None
358 self
.flavor_id
= None
361 super().__init
__(self
._cal
(), self
._account
(option
))
365 Loads rw.cal plugin via libpeas
367 plugin
= rw_peas
.PeasPlugin('rwcal_openstack', 'RwCal-1.0')
368 engine
, info
, extension
= plugin()
370 # Get the RwLogger context
371 rwloggerctx
= rwlogger
.RwLog
.Ctx
.new("Cal-Log")
373 cal
= plugin
.get_interface("Cloud")
375 rc
= cal
.init(rwloggerctx
)
376 assert rc
== RwStatus
.SUCCESS
378 logger
.error("ERROR:Cal plugin instantiation failed. Aborting tests")
380 logger
.info("Openstack Cal plugin successfully instantiated")
383 def _account(self
, option
):
384 """Cloud account information for Account
389 acct
= RwcalYang
.YangData_RwProject_Project_CloudAccounts_CloudAccountList
.from_dict({
390 "account_type": "openstack",
392 "key": option
.os_user
,
393 "secret": option
.os_password
,
394 "auth_url": 'http://{}:5000/v3/'.format(option
.os_host
),
395 "tenant": option
.os_tenant
,
396 "mgmt_network": option
.os_network
402 def _md5(self
, fname
, blksize
=1048576):
403 hash_md5
= hashlib
.md5()
404 with
open(fname
, "rb") as f
:
405 for chunk
in iter(lambda: f
.read(blksize
), b
""):
406 hash_md5
.update(chunk
)
407 return hash_md5
.hexdigest()
410 """Provides Image config for openstack.
415 image
= RwcalYang
.YangData_RwProject_Project_VimResources_ImageinfoList
.from_dict({
416 "name": rift
.auto
.mano
.resource_name(short_id()),
417 "location": os
.path
.join(os
.getenv("RIFT_ROOT"), "images/rift-root-latest.qcow2"),
418 "disk_format": "qcow2",
419 "container_format": "bare",
420 "checksum": self
._md
5(os
.path
.join(os
.getenv("RIFT_ROOT"), "images/rift-root-latest.qcow2")),
425 """Flavor config for openstack
430 flavor
= RwcalYang
.YangData_RwProject_Project_VimResources_FlavorinfoList
.from_dict({
431 "name": rift
.auto
.mano
.resource_name(short_id()),
438 "cpu_pinning_policy": "DEDICATED",
439 "cpu_thread_pinning_policy": "SEPARATE",
443 flavor
.guest_epa
.numa_node_policy
.node_cnt
= numa_node_count
444 for i
in range(numa_node_count
):
445 node
= flavor
.guest_epa
.numa_node_policy
.node
.add()
448 vcpu0
= node
.vcpu
.add()
450 vcpu1
= node
.vcpu
.add()
453 vcpu2
= node
.vcpu
.add()
455 vcpu3
= node
.vcpu
.add()
457 node
.memory_mb
= 8196
459 dev
= flavor
.guest_epa
.pcie_device
.add()
460 dev
.device_id
= "PCI_10G_ALIAS"
466 """Returns VDU config
471 vdu
= RwcalYang
.YangData_RwProject_Project_VduInitParams
.from_dict({
472 "name": rift
.auto
.mano
.resource_name(short_id()),
473 "node_id": "123456789012345",
474 "image_id": self
.image_id
,
475 "flavor_id": self
.flavor_id
,
478 c1
= vdu
.connection_points
.add()
479 c1
.name
= rift
.auto
.mano
.resource_name(short_id())
480 c1
.virtual_link_id
= self
.virtual_link_id
484 def virtual_link(self
):
485 """vlink config for Openstack
490 vlink
= RwcalYang
.YangData_RwProject_Project_VirtualLinkReqParams
.from_dict({
491 "name": rift
.auto
.mano
.resource_name(short_id()),
492 "subnet": '192.168.1.0/24',
498 @pytest.fixture(scope
="module", params
=[Openstack
], ids
=lambda val
: val
.__name
__)
499 def cloud_config(request
):
500 return request
.param(request
.config
.option
)
503 @pytest.mark
.incremental
506 def test_start_server(self
, cloud_config
):
507 cloud_config
.start_server()
509 def test_flavor_apis(self
, cloud_config
):
512 1. If the new flavor is created and available via read APIs
513 2. Verifies the READ APIs
515 account
= cloud_config
.account
516 cal
= cloud_config
.cal
518 status
, new_flavor_id
= cal
.create_flavor(account
, cloud_config
.flavor())
519 cloud_config
.flavor_id
= new_flavor_id
520 assert status
== RwStatus
.SUCCESS
522 status
, flavors
= cal
.get_flavor_list(account
)
523 assert status
== RwStatus
.SUCCESS
526 for flavor
in flavors
.flavorinfo_list
:
527 status
, flavor_single
= cal
.get_flavor(account
, flavor
.id)
528 assert status
== RwStatus
.SUCCESS
529 assert flavor
.id == flavor_single
.id
530 ids
.append(flavor
.id)
532 assert new_flavor_id
in ids
534 def test_image_apis(self
, cloud_config
):
537 1. If the new image is created and available via read APIs
538 2. Verifies the READ APIs
540 account
= cloud_config
.account
541 cal
= cloud_config
.cal
543 if type(cloud_config
) is Aws
:
545 new_image_id
= "ami-7070231a"
547 status
, new_image_id
= cal
.create_image(account
, cloud_config
.image())
548 cloud_config
.image_id
= new_image_id
549 assert status
== RwStatus
.SUCCESS
550 cloud_config
.check_state(new_image_id
, "get_image", "active")
553 status
, images
= cal
.get_image_list(account
)
556 for image
in images
.imageinfo_list
:
557 status
, image_single
= cal
.get_image(account
, image
.id)
558 assert status
== RwStatus
.SUCCESS
559 assert image_single
.id == image
.id
562 assert new_image_id
in ids
564 def test_virtual_link_create(self
, cloud_config
):
567 1. If the new Vlink is created and available via read APIs
568 2. Verifies the READ APIs
570 account
= cloud_config
.account
571 cal
= cloud_config
.cal
573 status
, new_vlink_id
= cal
.create_virtual_link(account
, cloud_config
.virtual_link())
574 cloud_config
.virtual_link_id
= new_vlink_id
575 assert status
.status
== RwStatus
.SUCCESS
576 cloud_config
.check_state(new_vlink_id
, "get_virtual_link", "active")
578 status
, vlinks
= cal
.get_virtual_link_list(account
)
579 assert status
== RwStatus
.SUCCESS
582 for vlink
in vlinks
.virtual_link_info_list
:
583 status
, vlink_single
= cal
.get_virtual_link(account
, vlink
.virtual_link_id
)
584 assert status
== RwStatus
.SUCCESS
585 assert vlink_single
.virtual_link_id
== vlink
.virtual_link_id
586 ids
.append(vlink
.virtual_link_id
)
588 assert new_vlink_id
in ids
590 def test_vdu_apis(self
, cloud_config
):
593 1. If the new VDU is created and available via read APIs
594 2. Verifies the READ APIs
596 account
= cloud_config
.account
597 cal
= cloud_config
.cal
599 status
, new_vdu_id
= cal
.create_vdu(account
, cloud_config
.vdu())
600 cloud_config
.vdu_id
= new_vdu_id
601 assert status
.status
== RwStatus
.SUCCESS
602 cloud_config
.check_state(new_vdu_id
, "get_vdu", "active")
604 status
, vdus
= cal
.get_vdu_list(account
)
605 assert status
== RwStatus
.SUCCESS
608 for vdu
in vdus
.vdu_info_list
:
609 status
, vdu_single
= cal
.get_vdu(account
, vdu
.vdu_id
, "")
610 assert status
== RwStatus
.SUCCESS
611 assert vdu_single
.vdu_id
== vdu
.vdu_id
612 ids
.append(vdu
.vdu_id
)
614 assert new_vdu_id
in ids
616 def test_modify_vdu_api(self
, cloud_config
):
617 account
= cloud_config
.account
618 cal
= cloud_config
.cal
620 vdu_modify
= RwcalYang
.YangData_RwProject_Project_VduModifyParams()
621 vdu_modify
.vdu_id
= cloud_config
.vdu_id
622 c1
= vdu_modify
.connection_points_add
.add()
623 c1
.name
= "c_modify1"
625 c1
.virtual_link_id
= cloud_config
.virtual_link_id
627 status
= cal
.modify_vdu(account
, vdu_modify
)
628 assert status
== RwStatus
.SUCCESS
630 @pytest.mark
.incremental
631 class TestCalTeardown
:
632 def test_flavor_delete(self
, cloud_config
):
635 1. If flavor is deleted
637 account
= cloud_config
.account
638 cal
= cloud_config
.cal
640 if type(cloud_config
) != Aws
:
641 status
= cal
.delete_flavor(account
, cloud_config
.flavor_id
)
642 assert status
== RwStatus
.SUCCESS
644 def test_image_delete(self
, cloud_config
):
647 1. If image is deleted
649 account
= cloud_config
.account
650 cal
= cloud_config
.cal
652 if type(cloud_config
) != Aws
:
653 status
= cal
.delete_image(account
, cloud_config
.image_id
)
654 assert status
== RwStatus
.SUCCESS
656 def test_virtual_link_delete(self
, cloud_config
):
659 1. If VLink is deleted
661 account
= cloud_config
.account
662 cal
= cloud_config
.cal
664 status
= cal
.delete_virtual_link(account
, cloud_config
.virtual_link_id
)
665 assert status
== RwStatus
.SUCCESS
667 def test_delete_vdu(self
, cloud_config
):
672 account
= cloud_config
.account
673 cal
= cloud_config
.cal
675 status
= cal
.delete_vdu(account
, cloud_config
.vdu_id
)
676 assert status
== RwStatus
.SUCCESS
678 def test_stop_server(self
, cloud_config
):
679 cloud_config
.stop_server()