Simple maas plugin for the example: Difference between revisions

From UNamur InfoSec
Jump to navigation Jump to search
(Created page with "== Introduction == OSM has include an example dummy VIM implementation here: [https://osm.etsi.org/gitweb/?p=osm/RO.git;a=blob;f=RO-plugin/osm_ro_plugin/vim_dummy.py;h=fe3a81...")
 
 
(3 intermediate revisions by the same user not shown)
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>
Line 17: Line 17:
from maas.client import login
from maas.client import login
import asyncio
import asyncio
from uuid import uuid4
from copy import deepcopy
from copy import deepcopy
import yaml
import yaml
Line 22: Line 23:
__author__ = ""
__author__ = ""
__date__ = ""
__date__ = ""


class vimconnector(vim_dummy.VimDummyConnector):
class vimconnector(vim_dummy.VimDummyConnector):
Line 40: Line 42:
             _, userdata = self._create_user_data(cloud_config)
             _, userdata = self._create_user_data(cloud_config)
             client = self._load_connection()
             client = self._load_connection()
             machine = client.machines.allocate()
            flavor = self.get_flavor(flavor_id)
             machine.deploy(user_data=userdata)
             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 = machine.system_id
             vm = {
             vm = {
Line 76: Line 80:
                 vms[vm_id] = vm
                 vms[vm_id] = vm
             return vms
             return vms
    def delete_vminstance(self, vm_id, created_items=None):
        client = self._load_connection()
        machine = client.machines.get(system_id=vm_id)
        machine.release()
        self.vms.pop(vm_id)
        return vm_id
   
    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
     #### private helper functions

Latest revision as of 14:59, 5 December 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 delete_vminstance(self, vm_id, created_items=None):
        client = self._load_connection()
        machine = client.machines.get(system_id=vm_id)
        machine.release()
        self.vms.pop(vm_id)
        return vm_id
    
    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