Simple maas plugin for the example: Difference between revisions

From UNamur InfoSec
Jump to navigation Jump to search
Line 8: Line 8:


== Source code ==
== Source code ==
The source code extends the vim_dummy file instead of vimconn file, and only implement two functions. The plugin does not check for deployment image, network, and machine specification yet.  
The source code extends the vim_dummy file instead of vimconn file, and only implement three functions.  


With these implementation, we can support deployed simple deployment with default MAAS configuration (default OS, default network, select first machine: instead of filter for machine by specification defined in NS descriptor)
With these implementation, we can support deployed simple NS deployment.


<pre>
<pre>

Revision as of 14:20, 30 November 2021

Introduction

OSM has include an example dummy VIM implementation here: [1](https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob;f=RO-plugin/osm_ro_plugin/vim_dummy.py;h=fe3a8115399fffb019ba90fe00698549676d59ed;hb=82954653961d69ce6a44ad26e992fb65db89f9ef)

The dummy VIM is a working VIM but only return dummy data to OSM.

To implement only the minimal deployment, we can extends the dummy VIM and only implement two functions: "new_vminstance", and "refresh_vms_status" functions.

Source code

The source code extends the vim_dummy file instead of vimconn file, and only implement three functions.

With these implementation, we can support deployed simple NS deployment.

import logging
from osm_ro_plugin import vim_dummy
from maas.client import login
import asyncio
from uuid import uuid4
from copy import deepcopy
import yaml

__author__ = ""
__date__ = ""


class vimconnector(vim_dummy.VimDummyConnector):

    def new_vminstance(
            self,
            name,
            description,
            start,
            image_id,
            flavor_id,
            net_list,
            cloud_config=None,
            disk_list=None,
            availability_zone_index=None,
            availability_zone_list=None,
        ):
            _, userdata = self._create_user_data(cloud_config)
            client = self._load_connection()
            flavor = self.get_flavor(flavor_id)
            machine = client.machines.allocate(cpus=flavor["vcpus"], memory=flavor["ram"])
            image = self.images[image_id]
            machine.deploy(user_data=userdata, distro_series=image["name"])
            vm_id = machine.system_id
            vm = {
                "id": vm_id,
                "name": name,
                "status": self._get_mapped_status(machine),
                "description": description,
                "interfaces": self._get_machine_interfaces(machine, net_list),
                "image_id": image_id,
                "flavor_id": flavor_id,
            }
            self.vms[vm_id] = vm
            return vm_id, vm
        
    def refresh_vms_status(self, vm_list):
            vms = {}
            client = self._load_connection()
            for vm_id in vm_list:
                try:
                    machine = client.machines.get(system_id=vm_id)
                    machine.refresh()
                    vm = deepcopy(self.vms[vm_id])
                    status = self._get_mapped_status(machine)
                    vm["vim_info"] = yaml.dump(
                        {"status": status, "name": vm["name"]},
                        default_flow_style=True,
                        width=256,
                    )
                    vm["status"] = status
                    for iface_index, iface in enumerate(vm["interfaces"]):
                        iface["ip_address"] = machine.interfaces[iface_index].links[iface_index].ip_address
                except Exception as e:
                    vm = {"status": "DELETED"}
                vms[vm_id] = vm
            return vms
    
    def get_image_list(self, filter_dict=None):
        images = []
        image_id = str(uuid4())
        image = deepcopy(filter_dict)
        image["id"] = image_id
        self.images[image_id] = image
        images.append(image)
        return images

    #### private helper functions
    def _load_connection(self):
            try:
                asyncio.get_event_loop()
            except RuntimeError as ex:
                if "There is no current event loop in thread" in str(ex):
                    loop = asyncio.new_event_loop()
                    asyncio.set_event_loop(loop)
            client = login(
                self.url,
                username=self.user, password=self.passwd,
            )
            return client

    def _get_mapped_status(self, machine):
            machine_status = machine.status.name
            power_state = machine.power_state.name
            if (machine_status == "DEPLOYING"):
                return "BUILD"
            if (machine_status == "DEPLOYED"):
                return "ACTIVE"
            return "SUSPENDED"

    def _get_machine_interfaces(self, machine, net_list):
        interfaces = []
        machine.refresh()
        for iface_index, iface in enumerate(net_list):
            iface["vim_id"] = str(iface_index)
            interface = {
                "ip_address": machine.interfaces[iface_index].links[iface_index].ip_address,
                "mac_address": machine.interfaces[iface_index].mac_address,
                "vim_interface_id": str(iface_index),
                "vim_net_id": iface["net_id"],
            }
            interfaces.append(interface)
        return interfaces