RIFT OSM R1 Initial Submission
[osm/SO.git] / rwcal / plugins / vala / rwcal_mock / rwcal_mock.py
diff --git a/rwcal/plugins/vala/rwcal_mock/rwcal_mock.py b/rwcal/plugins/vala/rwcal_mock/rwcal_mock.py
new file mode 100644 (file)
index 0000000..a1776d1
--- /dev/null
@@ -0,0 +1,616 @@
+
+# 
+#   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 random
+import socket
+import struct
+import collections
+import hashlib
+import logging
+import os
+import uuid
+
+from gi import require_version
+require_version('RwCal', '1.0')
+
+from gi.repository import (
+    GObject,
+    RwCal,
+    RwTypes,
+    RwcalYang)
+
+import rw_status
+import rift.cal.rwcal_status as rwcal_status
+import rwlogger
+
+logger = logging.getLogger('rwcal.mock')
+
+
+class UnknownAccountError(Exception):
+    pass
+
+
+class MissingFileError(Exception):
+    pass
+
+
+class ImageLocationError(Exception):
+    pass
+
+
+rwstatus_exception_map = { IndexError: RwTypes.RwStatus.NOTFOUND,
+                           KeyError: RwTypes.RwStatus.NOTFOUND,
+                           NotImplementedError: RwTypes.RwStatus.NOT_IMPLEMENTED,
+                           UnknownAccountError: RwTypes.RwStatus.NOTFOUND,
+                           MissingFileError: RwTypes.RwStatus.NOTFOUND,
+}
+
+rwstatus = rw_status.rwstatus_from_exc_map(rwstatus_exception_map)
+rwcalstatus = rwcal_status.rwcalstatus_from_exc_map(rwstatus_exception_map)
+
+class Resources(object):
+    def __init__(self):
+        self.images = dict()
+        self.vlinks = dict()
+        self.vdus  = dict()
+        self.flavors = dict()
+
+class MockPlugin(GObject.Object, RwCal.Cloud):
+    """This class implements the abstract methods in the Cloud class.
+    Mock is used for unit testing."""
+
+    def __init__(self):
+        GObject.Object.__init__(self)
+        self.resources = collections.defaultdict(Resources)
+
+    @staticmethod
+    def get_uuid(name):
+        if name == None:
+            raise ValueError("Name can not be None")
+        return str(uuid.uuid3(uuid.NAMESPACE_DNS, name))
+
+    @rwstatus
+    def do_init(self, rwlog_ctx):
+        if not any(isinstance(h, rwlogger.RwLogger) for h in logger.handlers):
+            logger.addHandler(
+                rwlogger.RwLogger(
+                    category="rw-cal-log",
+                    subcategory="rwcal.mock",
+                    log_hdl=rwlog_ctx,
+                )
+            )
+
+        account = RwcalYang.CloudAccount()
+        account.name = 'mock_account'
+        account.account_type = 'mock'
+        account.mock.username = 'mock_user'
+        self.create_default_resources(account)
+        account.name = 'mock_account1'
+        self.create_default_resources(account)
+
+    @rwstatus(ret_on_failure=[None])
+    def do_validate_cloud_creds(self, account):
+        """
+        Validates the cloud account credentials for the specified account.
+        If creds are not valid, returns an error code & reason string
+        Arguments:
+            account - a cloud account to validate
+
+        Returns:
+            Validation Code and Details String
+        """
+        status = RwcalYang.CloudConnectionStatus(
+                status="success",
+                details=""
+                )
+
+        return status
+
+    @rwstatus(ret_on_failure=[None])
+    def do_get_management_network(self, account):
+        """
+        Returns the management network
+
+        @param account - a cloud account
+
+        """
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_create_tenant(self, account, name):
+        """
+        Create a new tenant.
+
+        @param name     - name to assign to the tenant.
+        """
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_delete_tenant(self, account, tenant_id):
+        """
+        delete a tenant.
+
+        @param tenant_id     - id of tenant to be deleted.
+        """
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[[]])
+    def do_get_tenant_list(self, account):
+        """
+        List tenants.
+
+        """
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_create_role(self, account, name):
+        """
+        Create a new role.
+
+        @param name         - name to assign to the role.
+        """
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_delete_role(self, account, role_id):
+        """
+        delete a role.
+
+        @param role_id     - id of role to be deleted.
+        """
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[[]])
+    def do_get_role_list(self, account):
+        """
+        List roles.
+
+        """
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[None])
+    def do_create_image(self, account, image):
+        """
+        Create a VM image
+
+        @param account - cloud account information
+        @param image   - information about the image
+        """
+        if image.location is None:
+            raise ImageLocationError("uninitialized image location")
+
+        if not os.path.exists(image.location):
+            raise MissingFileError("{} does not exist".format(image.location))
+
+        image.id = self.get_uuid(image.name)
+
+        self.resources[account.name].images[image.id] = image
+        logger.debug('created image: {}'.format(image.id))
+        return image.id
+
+    @rwstatus
+    def do_delete_image(self, account, image_id):
+        """
+        delete a vm image.
+
+        @param image_id     - Instance id of VM image to be deleted.
+        """
+        if account.name not in self.resources:
+            raise UnknownAccountError()
+
+        del self.resources[account.name].images[image_id]
+
+    @rwstatus(ret_on_failure=[None])
+    def do_get_image(self, account, image_id):
+        return self.resources[account.name].images[image_id]
+
+    @rwstatus(ret_on_failure=[[]])
+    def do_get_image_list(self, account):
+        """
+        Return a list of the names of all available images.
+        """
+        boxed_image_list = RwcalYang.VimResources()
+        for image in self.resources[account.name].images.values():
+            image_entry = RwcalYang.ImageInfoItem()
+            image_entry.id = image.id
+            image_entry.name = image.name
+            if image.has_field('checksum'):
+
+                image_entry.checksum = image.checksum
+            boxed_image_list.imageinfo_list.append(image_entry)
+
+        logger.debug("Image list for {}: {}".format(account.name, boxed_image_list.imageinfo_list))
+        return boxed_image_list
+
+    @rwstatus
+    def do_create_vm(self, account, vm):
+        """
+        Create a new virtual machine.
+
+        @param name     - name to assign to the VM.  This does not have to be unique.
+        @param image    - name of image to load on the VM.
+        @param size     - name of the size of the VM to create.
+        @param location - name of the location to launch the VM in.
+        """
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_start_vm(self, account, vm_id):
+        """
+        Start a virtual machine.
+
+        @param vm_id - id of VM to start
+        """
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_stop_vm(self, account, vm_id):
+        """
+        Stop a virtual machine.
+
+        @param vm_id - id of VM to stop
+        """
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_delete_vm(self, account, vm_id):
+        """
+        delete a virtual machine.
+
+        @param vm_id     - Instance id of VM to be deleted.
+        """
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_reboot_vm(self, account, vm_id):
+        """
+        reboot a virtual machine.
+
+        @param vm_id     - Instance id of VM to be deleted.
+        """
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[[]])
+    def do_get_vm_list(self, account):
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_create_flavor(self, account, flavor):
+        """
+        create new flavor.
+
+        @param flavor   - Flavor object
+        """
+        flavor_id = self.get_uuid(flavor.name)
+        self.resources[account.name].flavors[flavor_id] = flavor
+        logger.debug('Created flavor: {}'.format(flavor_id))
+        return flavor_id
+
+    @rwstatus
+    def do_delete_flavor(self, account, flavor_id):
+        """
+        Delete flavor.
+
+        @param flavor_id     - Flavor id to be deleted.
+        """
+        logger.debug('Deleted flavor: {}'.format(flavor_id))
+        self.resources[account.name].flavors.pop(flavor_id)
+
+    @rwstatus(ret_on_failure=[None])
+    def do_get_flavor(self, account, flavor_id):
+        """
+        Return the specified flavor
+
+        @param flavor_id - the id of the flavor to return
+        """
+        flavor = self.resources[account.name].flavors[flavor_id]
+        logger.debug('Returning flavor-info for : {}'.format(flavor_id))
+        return flavor
+
+    @rwstatus(ret_on_failure=[[]])
+    def do_get_flavor_list(self, account):
+        """
+        Return a list of flavors
+        """
+        vim_resources = RwcalYang.VimResources()
+        for flavor in self.resources[account.name].flavors.values():
+            f = RwcalYang.FlavorInfoItem()
+            f.copy_from(flavor)
+            vim_resources.flavorinfo_list.append(f)
+        logger.debug("Returning list of flavor-info of size: %d", len(vim_resources.flavorinfo_list))
+        return vim_resources
+
+
+    @rwstatus
+    def do_add_host(self, account, host):
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_remove_host(self, account, host_id):
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[None])
+    def do_get_host(self, account, host_id):
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[[]])
+    def do_get_host_list(self, account):
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_create_port(self, account, port):
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_delete_port(self, account, port_id):
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[None])
+    def do_get_port(self, account, port_id):
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[[]])
+    def do_get_port_list(self, account):
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_create_network(self, account, network):
+        raise NotImplementedError()
+
+    @rwstatus
+    def do_delete_network(self, account, network_id):
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[None])
+    def do_get_network(self, account, network_id):
+        raise NotImplementedError()
+
+    @rwstatus(ret_on_failure=[[]])
+    def do_get_network_list(self, account):
+        raise NotImplementedError()
+
+    def create_default_resources(self, account):
+        """
+        Create default resources
+        """
+        link_list = []
+        ### Add virtual links
+        #for i in range(1):
+        #    vlink = RwcalYang.VirtualLinkReqParams()
+        #    vlink.name = 'link-'+str(i)
+        #    vlink.subnet = '10.0.0.0/24'
+        #    rs, vlink_id = self.do_create_virtual_link(account, vlink)
+        #    assert vlink_id != ''
+        #    logger.debug("Creating static virtual-link with name: %s", vlink.name)
+        #    link_list.append(vlink_id)
+
+        #### Add VDUs
+        #for i in range(8):
+        #    vdu = RwcalYang.VDUInitParams()
+        #    vdu.name = 'vdu-'+str(i)
+        #    vdu.node_id = str(i)
+        #    vdu.image_id = self.get_uuid('image-'+str(i))
+        #    vdu.flavor_id = self.get_uuid('flavor'+str(i))
+        #    vdu.vm_flavor.vcpu_count = 4
+        #    vdu.vm_flavor.memory_mb = 4096*2
+        #    vdu.vm_flavor.storage_gb = 40
+        #    for j in range(2):
+        #        c = vdu.connection_points.add()
+        #        c.name = vdu.name+'-port-'+str(j)
+        #        c.virtual_link_id = link_list[j]
+        #    rs, vdu_id = self.do_create_vdu(account, vdu)
+        #    assert vdu_id != ''
+        #    logger.debug("Creating static VDU with name: %s", vdu.name)
+
+        for i in range(2):
+            flavor = RwcalYang.FlavorInfoItem()
+            flavor.name = 'flavor-'+str(i)
+            flavor.vm_flavor.vcpu_count = 4
+            flavor.vm_flavor.memory_mb = 4096*2
+            flavor.vm_flavor.storage_gb = 40
+            rc, flavor_id = self.do_create_flavor(account, flavor)
+
+        for i in range(2):
+            image = RwcalYang.ImageInfoItem()
+            image.name = "rwimage"
+            image.id = self.get_uuid('image-'+str(i))
+            image.checksum = self.get_uuid('rwimage'+str(i))
+            image.location = "/dev/null"
+            rc, image_id = self.do_create_image(account, image)
+
+        image = RwcalYang.ImageInfoItem()
+        image.name = "Fedora-x86_64-20-20131211.1-sda.qcow2"
+        image.id = self.get_uuid(image.name)
+        image.checksum = self.get_uuid(image.name)
+        image.location = "/dev/null"
+        rc, image_id = self.do_create_image(account, image)
+
+        image = RwcalYang.ImageInfoItem()
+        image.name = "Fedora-x86_64-20-20131211.1-sda-ping.qcow2"
+        image.id = self.get_uuid(image.name)
+        image.checksum = "a6ffaa77f949a9e4ebb082c6147187cf"#self.get_uuid(image.name)
+        image.location = "/dev/null"
+        rc, image_id = self.do_create_image(account, image)
+
+        image = RwcalYang.ImageInfoItem()
+        image.name = "Fedora-x86_64-20-20131211.1-sda-pong.qcow2"
+        image.id = self.get_uuid(image.name)
+        image.checksum = "977484d95575f80ef8399c9cf1d45ebd"#self.get_uuid(image.name)
+        image.location = "/dev/null"
+        rc, image_id = self.do_create_image(account, image)
+
+
+    @rwcalstatus(ret_on_failure=[""])
+    def do_create_virtual_link(self, account, link_params):
+        vlink_id = self.get_uuid("%s_%s" % (link_params.name, len(self.resources[account.name].vlinks)))
+        vlink = RwcalYang.VirtualLinkInfoParams()
+        vlink.name = link_params.name
+        vlink.state = 'active'
+        vlink.virtual_link_id = vlink_id
+        vlink.subnet = link_params.subnet
+        vlink.connection_points = []
+        for field in link_params.provider_network.fields:
+            if link_params.provider_network.has_field(field):
+                setattr(vlink.provider_network, field, getattr(link_params.provider_network, field))
+
+        self.resources[account.name].vlinks[vlink_id] = vlink
+        logger.debug('created virtual-link: {}'.format(vlink_id))
+        return vlink_id
+
+    @rwstatus
+    def do_delete_virtual_link(self, account, link_id):
+        self.resources[account.name].vlinks.pop(link_id)
+        logger.debug('deleted virtual-link: {}'.format(link_id))
+
+
+    @rwstatus(ret_on_failure=[None])
+    def do_get_virtual_link(self, account, link_id):
+        vlink = self.resources[account.name].vlinks[link_id]
+        logger.debug('Returning virtual-link-info for : {}'.format(link_id))
+        return vlink
+
+    @rwstatus(ret_on_failure=[""])
+    def do_get_virtual_link_list(self, account):
+        vnf_resources = RwcalYang.VNFResources()
+        for r in self.resources[account.name].vlinks.values():
+            vlink = RwcalYang.VirtualLinkInfoParams()
+            vlink.copy_from(r)
+            vnf_resources.virtual_link_info_list.append(vlink)
+        logger.debug("Returning list of virtual-link-info of size: %d", len(vnf_resources.virtual_link_info_list))
+        return vnf_resources
+
+    @rwcalstatus(ret_on_failure=[""])
+    def do_create_vdu(self, account, vdu_init):
+        vdu_id = self.get_uuid("%s_%s" % (vdu_init.name, len(self.resources[account.name].vdus)))
+        vdu = RwcalYang.VDUInfoParams()
+        vdu.vdu_id = vdu_id
+        vdu.name = vdu_init.name
+        vdu.node_id = vdu_init.node_id
+        vdu.image_id = vdu_init.image_id
+        if vdu_init.has_field('flavor_id'):
+            vdu.flavor_id = vdu_init.flavor_id
+
+        if vdu_init.has_field('vm_flavor'):
+            xx = vdu.vm_flavor.new()
+            xx.from_pbuf(vdu_init.vm_flavor.to_pbuf())
+            vdu.vm_flavor = xx
+
+        if vdu_init.has_field('guest_epa'):
+            xx = vdu.guest_epa.new()
+            xx.from_pbuf(vdu_init.guest_epa.to_pbuf())
+            vdu.guest_epa = xx
+
+        if vdu_init.has_field('vswitch_epa'):
+            xx = vdu.vswitch_epa.new()
+            xx.from_pbuf(vdu_init.vswitch_epa.to_pbuf())
+            vdu.vswitch_epa = xx
+
+        if vdu_init.has_field('hypervisor_epa'):
+            xx = vdu.hypervisor_epa.new()
+            xx.from_pbuf(vdu_init.hypervisor_epa.to_pbuf())
+            vdu.hypervisor_epa = xx
+
+        if vdu_init.has_field('host_epa'):
+            xx = vdu.host_epa.new()
+            xx.from_pbuf(vdu_init.host_epa.to_pbuf())
+            vdu.host_epa = xx
+
+        vdu.state = 'active'
+        vdu.management_ip = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+        vdu.public_ip = vdu.management_ip
+
+        for c in vdu_init.connection_points:
+            p = vdu.connection_points.add()
+            p.connection_point_id = self.get_uuid(c.name)
+            p.name = c.name
+            p.vdu_id = vdu_id
+            p.state = 'active'
+            p.ip_address = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+            p.virtual_link_id = c.virtual_link_id
+            # Need to add this connection_point to virtual link
+            vlink = self.resources[account.name].vlinks[c.virtual_link_id]
+            v = vlink.connection_points.add()
+            for field in p.fields:
+                if p.has_field(field):
+                    setattr(v, field, getattr(p, field))
+
+        self.resources[account.name].vdus[vdu_id] = vdu
+        logger.debug('Created vdu: {}'.format(vdu_id))
+        return vdu_id
+
+
+    @rwstatus
+    def do_modify_vdu(self, account, vdu_modify):
+        vdu = self.resources[account.name].vdus[vdu_modify.vdu_id]
+        for c in vdu_modify.connection_points_add:
+            p = vdu.connection_points.add()
+            p.connection_point_id = self.get_uuid(c.name)
+            p.name = c.name
+            p.vdu_id = vdu.vdu_id
+            p.state = 'active'
+            p.ip_address = socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
+            p.virtual_link_id = c.virtual_link_id
+            # Need to add this connection_point to virtual link
+            vlink = self.resources[account.name].vlinks[c.virtual_link_id]
+            aa = RwcalYang.VirtualLinkInfoParams_ConnectionPoints()
+            aa.connection_point_id = p.connection_point_id
+            aa.name = p.name
+            aa.virtual_link_id = vlink.virtual_link_id
+            aa.state = 'active'
+            aa.ip_address = p.ip_address
+            aa.vdu_id = p.vdu_id
+            vlink.connection_points.append(aa)
+
+        for c in vdu_modify.connection_points_remove:
+            for d in vdu.connection_points:
+                if c.connection_point_id == d.connection_point_id:
+                    vdu.connection_points.remove(d)
+                    break
+            for k, vlink in self.resources[account.name].vlinks.items():
+                for z in vlink.connection_points:
+                    if z.connection_point_id == c.connection_point_id:
+                        vlink.connection_points.remove(z)
+                        break
+        logger.debug('modified vdu: {}'.format(vdu_modify.vdu_id))
+
+    @rwstatus
+    def do_delete_vdu(self, account, vdu_id):
+        vdu = self.resources[account.name].vdus.pop(vdu_id)
+        for c in vdu.connection_points:
+            vlink = self.resources[account.name].vlinks[c.virtual_link_id]
+            z = [p for p in vlink.connection_points if p.connection_point_id == c.connection_point_id]
+            assert len(z) == 1
+            vlink.connection_points.remove(z[0])
+
+        logger.debug('deleted vdu: {}'.format(vdu_id))
+
+    @rwstatus(ret_on_failure=[None])
+    def do_get_vdu(self, account, vdu_id):
+        vdu = self.resources[account.name].vdus[vdu_id]
+        logger.debug('Returning vdu-info for : {}'.format(vdu_id))
+        return vdu.copy()
+
+    @rwstatus(ret_on_failure=[""])
+    def do_get_vdu_list(self, account):
+        vnf_resources = RwcalYang.VNFResources()
+        for r in self.resources[account.name].vdus.values():
+            vdu = RwcalYang.VDUInfoParams()
+            vdu.copy_from(r)
+            vnf_resources.vdu_info_list.append(vdu)
+        logger.debug("Returning list of vdu-info of size: %d", len(vnf_resources.vdu_info_list))
+        return vnf_resources
+