Esempio n. 1
0
    def get_image_id_from_path(self, path):
        """
        For FaaS VIM, image name is the fully qualified name of the action.
        Because of that RO thinks image name is a pathname and calls this
        method.

        Note: In case action not found, vimconnException exception get thrown
        so that RO does not try to create it. Remember, FaaS does not manage
        images
        """
        self.logger.debug(LOG_PREFIX + "get_image_id_from_path: '%s'", path)
        action_name = path
        try:
            validate_action_name(action_name)
            r = requestAction(self.logger, self.owAPIHost, self.owb64APIKey,
                              action_name)
            r_json = r.json()
        except HTTPError as http_error:
            if http_error.response.status_code == 404:
                raise vimconn.vimconnException(
                    "Action name '{}' not found".format(action_name))
            else:
                raise vimconn.vimconnException(str(http_error))
        except Exception as e:
            raise vimconn.vimconnException(str(e))

        a = find(r_json['annotations'],
                 lambda a: a['key'] == image_annotation_key)
        image_id = a['value'] if a else ''
        self.logger.info(LOG_PREFIX + "get_image_id_from_path: "
                         "'%(image_annotation_key)s': '%(image_id)s'" % {
                             'image_annotation_key': image_annotation_key,
                             'image_id': image_id
                         })
        if not image_id:
            image_id = generate_unicode_uuid(seed=action_name)
            self.logger.debug(
                LOG_PREFIX +
                "get_image_id_from_path: No image_id found for action: "
                "%(action_name)s. Generated new uuid: %(image_id)s" % {
                    'action_name': action_name,
                    'image_id': image_id
                })
            updateActionAnnotation(self.logger, self.owAPIHost,
                                   self.owb64APIKey, action_name,
                                   image_annotation_key, image_id)

        return image_id
Esempio n. 2
0
 def get_network(self, net_id):
     """Obtain network details from the 'net_id' VIM network
     Return a dict that contains:
         'id': (mandatory) VIM network id, that is, net_id
         'name': (mandatory) VIM network name
         'status': (mandatory) can be 'ACTIVE', 'INACTIVE', 'DOWN', 'BUILD', 'ERROR', 'VIM_ERROR', 'OTHER'
         'error_msg': (optional) text that explains the ERROR status
         other VIM specific fields: (optional) whenever possible using the same naming of filter_dict param
     Raises an exception upon error or when network is not found
     """
     try:
         one = self._new_one_connection()
         net_pool = one.vnpool.info(-2, -1, -1).VNET
         net = {}
         for network in net_pool:
             if str(network.ID) == str(net_id):
                 net['id'] = network.ID
                 net['name'] = network.NAME
                 net['status'] = "ACTIVE"
                 break
         if net:
             return net
         else:
             raise vimconn.vimconnNotFoundException(
                 "Network {} not found".format(net_id))
     except Exception as e:
         self.logger.error("Get network " + str(net_id) + " error): " +
                           str(e))
         raise vimconn.vimconnException(e)
Esempio n. 3
0
 def get_image_list(self, filter_dict={}):
     """Obtain tenant images from VIM
     Filter_dict can be:
         name: image name
         id: image uuid
         checksum: image checksum
         location: image path
     Returns the image list of dictionaries:
         [{<the fields at Filter_dict plus some VIM specific>}, ...]
         List can be empty
     """
     try:
         one = self._new_one_connection()
         image_pool = one.imagepool.info(-2, -1, -1).IMAGE
         images = []
         if "name" in filter_dict.keys():
             image_name_filter = filter_dict["name"]
         else:
             image_name_filter = None
         if "id" in filter_dict.keys():
             image_id_filter = filter_dict["id"]
         else:
             image_id_filter = None
         for image in image_pool:
             if str(image_name_filter) == str(image.NAME) or str(
                     image.ID) == str(image_id_filter):
                 images_dict = {"name": image.NAME, "id": str(image.ID)}
                 images.append(images_dict)
         return images
     except Exception as e:
         self.logger.error("Get image list error: " + str(e))
         raise vimconn.vimconnException(e)
Esempio n. 4
0
    def delete_vminstance(self, vm_id, created_items=None):
        """
        Removes a VM instance from VIM and its associated elements
        :param vm_id: VIM identifier of the VM, provided by method new_vminstance
        :param created_items: dictionary with extra items to be deleted. provided by method new_vminstance and/or method
            action_vminstance
        :return: None or the same vm_id. Raises an exception on fail
        """
        try:
            one = self._new_one_connection()
            one.vm.recover(int(vm_id), 3)
            vm = None
            while True:
                if vm is not None and vm.LCM_STATE == 0:
                    break
                else:
                    vm = one.vm.info(int(vm_id))

        except pyone.OneNoExistsException as e:
            self.logger.info("The vm " + str(vm_id) +
                             " does not exist or is already deleted")
            raise vimconn.vimconnNotFoundException(
                "The vm {} does not exist or is already deleted".format(vm_id))
        except Exception as e:
            self.logger.error("Delete vm instance " + str(vm_id) + " error: " +
                              str(e))
            raise vimconn.vimconnException(e)
Esempio n. 5
0
 def new_tenant(self, tenant_name, tenant_description):
     # '''Adds a new tenant to VIM with this name and description, returns the tenant identifier'''
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         group_list = oca.GroupPool(client)
         user_list = oca.UserPool(client)
         group_list.info()
         user_list.info()
         create_primarygroup = 1
         # create group-tenant
         for group in group_list:
             if str(group.name) == str(tenant_name):
                 create_primarygroup = 0
                 break
         if create_primarygroup == 1:
             oca.Group.allocate(client, tenant_name)
         group_list.info()
         # set to primary_group the tenant_group and oneadmin to secondary_group
         for group in group_list:
             if str(group.name) == str(tenant_name):
                 for user in user_list:
                     if str(user.name) == str(self.user):
                         if user.name == "oneadmin":
                             return str(0)
                         else:
                             self._add_secondarygroup(user.id, group.id)
                             user.chgrp(group.id)
                             return str(group.id)
     except Exception as e:
         self.logger.error("Create new tenant error: " + str(e))
         raise vimconn.vimconnException(e)
Esempio n. 6
0
    def _new_subnet(self, net_name, ip_profile):
        """
        Adds a tenant network to VIM. It creates a new VNET with a single subnet
        :param net_name:
        :param ip_profile:
        :return:
        """
        self.logger.debug('Adding a subnet to VNET '+self.vnet_name)
        self._reload_connection()

        if ip_profile is None:
            # TODO get a non used vnet ip range /24 and allocate automatically
            raise vimconn.vimconnException('Azure cannot create VNET with no CIDR')

        try:
            vnet_params= {
                'location': self.region,
                'address_space': {
                    'address_prefixes': [ip_profile['subnet_address']]
                },
                'subnets': [
                    {
                        'name': "{}-{}".format(net_name[:24], uuid4()),
                        'address_prefix': ip_profile['subnet_address']
                    }
                ]
            }
            self.conn_vnet.virtual_networks.create_or_update(self.resource_group, self.vnet_name, vnet_params)
            # TODO return a tuple (subnet-ID, None)
        except Exception as e:
            self.format_vimconn_exception(e)
    def new_network(self, net_name, net_type, ip_profile=None, shared=False, vlan=None):  # , **vim_specific):
        """Returns the network identifier"""
        # oca library method cannot be used in this case (problem with cluster parameters)
        try:
            # vlan = str(random.randint(self.config["vlan"]["start-range"], self.config["vlan"]["finish-range"]))
            # self.create_bridge_host(vlan)
            bridge_config = self.config["bridge_service"]
            ip_version = "IP4"
            size = "256"
            if ip_profile is None:
                random_number_ipv4 = random.randint(1, 255)
                ip_start = "192.168." + str(random_number_ipv4) + ".1"  # random value
            else:
                index = ip_profile["subnet_address"].find("/")
                ip_start = ip_profile["subnet_address"][:index]
                if "dhcp_count" in ip_profile.keys() and ip_profile["dhcp_count"] is not None:
                    size = str(ip_profile["dhcp_count"])
                elif not ("dhcp_count" in ip_profile.keys()) and ip_profile["ip_version"] == "IPv4":
                    prefix = ip_profile["subnet_address"][index + 1:]
                    size = int(math.pow(2, 32 - prefix))
                if "dhcp_start_address" in ip_profile.keys() and ip_profile["dhcp_start_address"] is not None:
                    ip_start = str(ip_profile["dhcp_start_address"])
                if ip_profile["ip_version"] == "IPv6":
                    ip_version = "IP6"
            if ip_version == "IP6":
                config = "NAME = {}\
                        BRIDGE = {}\
                        VN_MAD = dummy\
                        AR = [TYPE = {}, GLOBAL_PREFIX = {}, SIZE = {}]".format(net_name, bridge_config, ip_version,
                                                                                ip_start, size)
            else:
                config = 'NAME = "{}"\
                        BRIDGE = {}\
                        VN_MAD = dummy\
                        AR = [TYPE = {}, IP = {}, SIZE = {}]'.format(net_name, bridge_config, ip_version, ip_start,
                                                                     size)

            params = '<?xml version="1.0"?> \
            <methodCall>\
            <methodName>one.vn.allocate</methodName>\
            <params>\
            <param>\
            <value><string>{}:{}</string></value>\
            </param>\
            <param>\
            <value><string>{}</string></value>\
            </param>\
            <param>\
            <value><int>{}</int></value>\
            </param>\
            </params>\
            </methodCall>'.format(self.user, self.passwd, config, self.config["cluster"]["id"])
            r = requests.post(self.url, params)
            obj = untangle.parse(str(r.content))
            return obj.methodResponse.params.param.value.array.data.value[1].i4.cdata.encode('utf-8')
        except Exception as e:
            self.logger.error("Create new network error: " + str(e))
            raise vimconn.vimconnException(e)
 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):
     """Adds a VM instance to VIM
     Params:
         start: indicates if VM must start or boot in pause mode. Ignored
         image_id,flavor_id: image and flavor uuid
         net_list: list of interfaces, each one is a dictionary with:
             name:
             net_id: network uuid to connect
             vpci: virtual vcpi to assign
             model: interface model, virtio, e2000, ...
             mac_address:
             use: 'data', 'bridge',  'mgmt'
             type: 'virtual', 'PF', 'VF', 'VFnotShared'
             vim_id: filled/added by this function
             #TODO ip, security groups
     Returns the instance identifier
     """
     self.logger.debug(
         "new_vminstance input: image='{}' flavor='{}' nics='{}'".format(image_id, flavor_id, str(net_list)))
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         listaTemplate = oca.VmTemplatePool(client)
         listaTemplate.info()
         for template in listaTemplate:
             if str(template.id) == str(flavor_id):
                 cpu = ' CPU = "{}"'.format(template.template.cpu)
                 memory = ' MEMORY = "{}"'.format(template.template.memory)
                 context = ' CONTEXT = [NETWORK = "YES",SSH_PUBLIC_KEY = "$USER[SSH_PUBLIC_KEY]" ]'
                 graphics = ' GRAPHICS = [ LISTEN = "0.0.0.0", TYPE = "VNC" ]'
                 disk = ' DISK = [ IMAGE_ID = {}]'.format(image_id)
                 sched_requeriments = ' SCHED_REQUIREMENTS = "CLUSTER_ID={}"'.format(self.config["cluster"]["id"])
                 template_updated = cpu + memory + context + graphics + disk + sched_requeriments
                 networkListVim = oca.VirtualNetworkPool(client)
                 networkListVim.info()
                 network = ""
                 for net in net_list:
                     network_found = False
                     for network_existingInVim in networkListVim:
                         if str(net["net_id"]) == str(network_existingInVim.id):
                             net["vim_id"] = network_existingInVim["id"]
                             network = 'NIC = [NETWORK = "{}",NETWORK_UNAME = "{}" ]'.format(
                                 network_existingInVim.name, network_existingInVim.uname)
                             network_found = True
                             break
                     if not network_found:
                         raise vimconn.vimconnNotFoundException("Network {} not found".format(net["net_id"]))
                     template_updated += network
                 oca.VmTemplate.update(template, template_updated)
                 self.logger.info(
                     "Instanciating in OpenNebula a new VM name:{} id:{}".format(template.name, template.id))
                 vminstance_id = template.instantiate(name=name)
                 return str(vminstance_id), None
         raise vimconn.vimconnNotFoundException("Flavor {} not found".format(flavor_id))
     except Exception as e:
         self.logger.error("Create new vm instance error: " + str(e))
         raise vimconn.vimconnException(e)
Esempio n. 9
0
    def get_image_list(self, filter_dict={}):
        # TODO: Is it a dead code?
        """
        RO passes the name of the image set in vnfd:vdu
        For FaaS VIM, image name is the fully qualified name of the action.

        In OW we do not have the uuid of the action. Thus we fake such a one
        here (if does not exist) and store it under persistent_info dictionary
        managed by RO.

        That uuid will be passed in `new_vminstance` and we use the
        persistent_info mapping to retrieve back action name

        :param filter_dict: Filtering dictionary that contains the fully
                            qualified name of the action
        :type filter_dict: ``dict``

        :return: ``list`` of single action uuid, empty list if action not
                found
        """
        self.logger.debug(LOG_PREFIX + "get_image_list: filter_dict: '%s'",
                          filter_dict)

        action_name = filter_dict['name']
        try:
            validate_action_name(action_name)
        except Exception as e:
            raise vimconn.vimconnException("Error validating action: %s" %
                                           str(e))

        try:
            requestAction(self.logger, self.owAPIHost, self.owb64APIKey,
                          action_name)
        except Exception as e:
            self.logger.error(LOG_PREFIX +
                              "Error occurred during action retrieval: %s" %
                              str(e))
            image_list = []
        else:
            action_uuid = self.persistent_info['actions'].get(action_name)
            if not action_uuid:
                action_uuid = generate_unicode_uuid()
                self.persistent_info['actions'][action_name] = action_uuid

                self.logger.debug(
                    LOG_PREFIX + "get_image_list: No uuid found for action: "
                    "%(action_name)s. Generated new uuid: %(action_uuid)s" % {
                        'action_name': action_name,
                        'action_uuid': action_uuid
                    })

            image_list = [{'id': action_uuid}]

        self.logger.debug(LOG_PREFIX +
                          "get_image_list: RETURN '%s'" % image_list)

        return image_list
Esempio n. 10
0
 def get_vminstance(self, vm_id):
     """Returns the VM instance information from VIM"""
     try:
         one = self._new_one_connection()
         vm = one.vm.info(int(vm_id))
         return vm
     except Exception as e:
         self.logger.error("Getting vm instance error: " + str(e) +
                           ": VM Instance not found")
         raise vimconn.vimconnException(e)
 def delete_vminstance(self, vm_id, created_items=None):
     """Removes a VM instance from VIM, returns the deleted vm_id"""
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         vm_pool = oca.VirtualMachinePool(client)
         vm_pool.info()
         vm_exist = False
         for i in vm_pool:
             if str(i.id) == str(vm_id):
                 vm_exist = True
                 break
         if not vm_exist:
             self.logger.info("The vm " + str(vm_id) + " does not exist or is already deleted")
             raise vimconn.vimconnNotFoundException("The vm {} does not exist or is already deleted".format(vm_id))
         params = '<?xml version="1.0"?> \
                     <methodCall>\
                     <methodName>one.vm.recover</methodName>\
                     <params>\
                     <param>\
                     <value><string>{}:{}</string></value>\
                     </param>\
                     <param>\
                     <value><int>{}</int></value>\
                     </param>\
                     <param>\
                     <value><int>{}</int></value>\
                     </param>\
                     </params>\
                     </methodCall>'.format(self.user, self.passwd, str(vm_id), str(3))
         r = requests.post(self.url, params)
         obj = untangle.parse(str(r.content))
         response_success = obj.methodResponse.params.param.value.array.data.value[0].boolean.cdata.encode('utf-8')
         response = obj.methodResponse.params.param.value.array.data.value[1].i4.cdata.encode('utf-8')
         # response can be the resource ID on success or the error string on failure.
         response_error_code = obj.methodResponse.params.param.value.array.data.value[2].i4.cdata.encode('utf-8')
         if response_success.lower() == "true":
             return response
         else:
             raise vimconn.vimconnException("vm {} cannot be deleted with error_code {}: {}".format(vm_id, response_error_code, response))
     except Exception as e:
         self.logger.error("Delete vm instance " + str(vm_id) + " error: " + str(e))
         raise vimconn.vimconnException(e)
Esempio n. 12
0
    def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None,
                 config={}, persistent_info={}):

        vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level,
                                      config, persistent_info)

        # LOGGER
        self.logger = logging.getLogger('openmano.vim.azure')
        if log_level:
            logging.basicConfig()
            self.logger.setLevel(getattr(logging, log_level))

        # CREDENTIALS 
        self.credentials = ServicePrincipalCredentials(
            client_id=user,
            secret=passwd,
            tenant=(tenant_id or tenant_name)
        )

        # SUBSCRIPTION
        if 'subscription_id' in config:
            self.subscription_id = config.get('subscription_id')
            self.logger.debug('Setting subscription '+str(self.subscription_id))
        else:
            raise vimconn.vimconnException('Subscription not specified')
        # REGION
        if 'region_name' in config:
            self.region = config.get('region_name')
        else:
            raise vimconn.vimconnException('Azure region_name is not specified at config')
        # RESOURCE_GROUP
        if 'resource_group' in config:
            self.resource_group = config.get('resource_group')
        else:
            raise vimconn.vimconnException('Azure resource_group is not specified at config')
        # VNET_NAME
        if 'vnet_name' in config:
            self.vnet_name = config["vnet_name"]
            
        # public ssh key
        self.pub_key = config.get('pub_key')
Esempio n. 13
0
 def delete_flavor(self, flavor_id):
     """ Deletes a tenant flavor from VIM
         Returns the old flavor_id
     """
     try:
         one = self._new_one_connection()
         one.template.delete(int(flavor_id), False)
         return flavor_id
     except Exception as e:
         self.logger.error("Error deleting flavor " + str(flavor_id) +
                           ". Flavor not found")
         raise vimconn.vimconnException(e)
 def get_flavor(self, flavor_id):  # Esta correcto
     """Obtain flavor details from the  VIM"""
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         listaTemplate = oca.VmTemplatePool(client)
         listaTemplate.info()
         for template in listaTemplate:
             if str(template.id) == str(flavor_id):
                 return {'id': template.id, 'name': template.name}
         raise vimconn.vimconnNotFoundException("Flavor {} not found".format(flavor_id))
     except Exception as e:
         self.logger.error("get flavor " + str(flavor_id) + " error: " + str(e))
         raise vimconn.vimconnException(e)
Esempio n. 15
0
 def get_vminstance_console(self,vm_id, console_type="vnc"):
     '''
     Get a console for the virtual machine
     Params:
         vm_id: uuid of the VM
         console_type, can be:
             "novnc" (by default), "xvpvnc" for VNC types, 
             "rdp-html5" for RDP types, "spice-html5" for SPICE types
     Returns dict with the console parameters:
             protocol: ssh, ftp, http, https, ...
             server:   usually ip address 
             port:     the http, ssh, ... port 
             suffix:   extra text, e.g. the http path and query string   
     '''
     self.logger.debug("Getting VM CONSOLE from VIM")
     try:
         self._reload_connection()
         server = self.nova.servers.find(id=vm_id)
         if console_type == None or console_type == "novnc":
             console_dict = server.get_vnc_console("novnc")
         elif console_type == "xvpvnc":
             console_dict = server.get_vnc_console(console_type)
         elif console_type == "rdp-html5":
             console_dict = server.get_rdp_console(console_type)
         elif console_type == "spice-html5":
             console_dict = server.get_spice_console(console_type)
         else:
             raise vimconn.vimconnException("console type '{}' not allowed".format(console_type), http_code=vimconn.HTTP_Bad_Request)
         
         console_dict1 = console_dict.get("console")
         if console_dict1:
             console_url = console_dict1.get("url")
             if console_url:
                 #parse console_url
                 protocol_index = console_url.find("//")
                 suffix_index = console_url[protocol_index+2:].find("/") + protocol_index+2
                 port_index = console_url[protocol_index+2:suffix_index].find(":") + protocol_index+2
                 if protocol_index < 0 or port_index<0 or suffix_index<0:
                     return -vimconn.HTTP_Internal_Server_Error, "Unexpected response from VIM"
                 console_dict={"protocol": console_url[0:protocol_index],
                               "server":   console_url[protocol_index+2:port_index], 
                               "port":     console_url[port_index:suffix_index], 
                               "suffix":   console_url[suffix_index+1:] 
                               }
                 protocol_index += 2
                 return console_dict
         raise vimconn.vimconnUnexpectedResponse("Unexpected response from VIM")
         
     except (nvExceptions.NotFound, ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.BadRequest) as e:
         self._format_exception(e)
Esempio n. 16
0
    def new_flavor(self, flavor_data):
        """Adds a tenant flavor to VIM
            flavor_data contains a dictionary with information, keys:
                name: flavor name
                ram: memory (cloud type) in MBytes
                vpcus: cpus (cloud type)
                extended: EPA parameters
                  - numas: #items requested in same NUMA
                        memory: number of 1G huge pages memory
                        paired-threads|cores|threads: number of paired hyperthreads, complete cores OR individual threads
                        interfaces: # passthrough(PT) or SRIOV interfaces attached to this numa
                          - name: interface name
                            dedicated: yes|no|yes:sriov;  for PT, SRIOV or only one SRIOV for the physical NIC
                            bandwidth: X Gbps; requested guarantee bandwidth
                            vpci: requested virtual PCI address
                disk: disk size
                is_public:
                 #TODO to concrete
        Returns the flavor identifier"""

        disk_size = str(int(flavor_data["disk"]) * 1024)

        try:
            one = self._new_one_connection()
            template_id = one.template.allocate({
                'TEMPLATE': {
                    'NAME': flavor_data["name"],
                    'CPU': flavor_data["vcpus"],
                    'VCPU': flavor_data["vcpus"],
                    'MEMORY': flavor_data["ram"],
                    'DISK': {
                        'SIZE': disk_size
                    },
                    'CONTEXT': {
                        'NETWORK': "YES",
                        'SSH_PUBLIC_KEY': '$USER[SSH_PUBLIC_KEY]'
                    },
                    'GRAPHICS': {
                        'LISTEN': '0.0.0.0',
                        'TYPE': 'VNC'
                    },
                    'CLUSTER_ID': self.config["cluster"]["id"]
                }
            })
            return template_id

        except Exception as e:
            self.logger.error("Create new flavor error: " + str(e))
            raise vimconn.vimconnException(e)
Esempio n. 17
0
 def delete_network(self, net_id):
     """Deletes a tenant network from VIM
     Returns the network identifier or raises an exception upon error or when network is not found
     """
     self.logger.debug('delete_network: {}'.format(net_id))
     try:
         self.fos_api.network.remove_network(net_id)
     except fimerrors.FIMNotFoundException as fnfe:
         raise vimconn.vimconnNotFoundException(
             "Network {} not found at VIM (already deleted?). Error {}".
             format(net_id, fnfe))
     except Exception as e:
         raise vimconn.vimconnException(
             "Cannot delete network {} from VIM. Error {}".format(
                 net_id, e))
     return net_id
Esempio n. 18
0
    def delete_network(self, net_id, created_items=None):
        """
        Removes a tenant network from VIM and its associated elements
        :param net_id: VIM identifier of the network, provided by method new_network
        :param created_items: dictionary with extra items to be deleted. provided by method new_network
        Returns the network identifier or raises an exception upon error or when network is not found
        """
        try:

            one = self._new_one_connection()
            one.vn.delete(int(net_id))
            return net_id
        except Exception as e:
            self.logger.error("Delete network " + str(net_id) +
                              "error: network not found" + str(e))
            raise vimconn.vimconnException(e)
Esempio n. 19
0
    def get_network_list(self, filter_dict={}):
        """Obtain tenant networks of VIM
        Params:
            'filter_dict' (optional) contains entries to return only networks that matches ALL entries:
                name: string  => returns only networks with this name
                id:   string  => returns networks with this VIM id, this imply returns one network at most
                shared: boolean >= returns only networks that are (or are not) shared
                tenant_id: sting => returns only networks that belong to this tenant/project
                ,#(not used yet) admin_state_up: boolean => returns only networks that are (or are not) in admin state active
                #(not used yet) status: 'ACTIVE','ERROR',... => filter networks that are on this status
        Returns the network list of dictionaries. each dictionary contains:
            'id': (mandatory) VIM network id
            'name': (mandatory) VIM network name
            'status': (mandatory) can be 'ACTIVE', 'INACTIVE', 'DOWN', 'BUILD', 'ERROR', 'VIM_ERROR', 'OTHER'
            'network_type': (optional) can be 'vxlan', 'vlan' or 'flat'
            'segmentation_id': (optional) in case network_type is vlan or vxlan this field contains the segmentation id
            'error_msg': (optional) text that explains the ERROR status
            other VIM specific fields: (optional) whenever possible using the same naming of filter_dict param
        List can be empty if no network map the filter_dict. Raise an exception only upon VIM connectivity,
            authorization, or some other unspecific error
        """

        try:
            one = self._new_one_connection()
            net_pool = one.vnpool.info(-2, -1, -1).VNET
            response = []
            if "name" in filter_dict.keys():
                network_name_filter = filter_dict["name"]
            else:
                network_name_filter = None
            if "id" in filter_dict.keys():
                network_id_filter = filter_dict["id"]
            else:
                network_id_filter = None
            for network in net_pool:
                if network.NAME == network_name_filter or str(
                        network.ID) == str(network_id_filter):
                    net_dict = {
                        "name": network.NAME,
                        "id": str(network.ID),
                        "status": "ACTIVE"
                    }
                    response.append(net_dict)
            return response
        except Exception as e:
            self.logger.error("Get network list error: " + str(e))
            raise vimconn.vimconnException(e)
 def delete_flavor(self, flavor_id):
     """ Deletes a tenant flavor from VIM
         Returns the old flavor_id
     """
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         listaTemplate = oca.VmTemplatePool(client)
         listaTemplate.info()
         self.logger.info("Deleting VIM flavor DELETE {}".format(self.url))
         for template in listaTemplate:
             if str(template.id) == str(flavor_id):
                 template.delete()
                 return template.id
         raise vimconn.vimconnNotFoundException("Flavor {} not found".format(flavor_id))
     except Exception as e:
         self.logger.error("Delete flavor " + str(flavor_id) + " error: " + str(e))
         raise vimconn.vimconnException(e)
Esempio n. 21
0
    def get_flavor(self, flavor_id):  # Esta correcto
        """Obtain flavor details from the VIM
        Returns the flavor dict details {'id':<>, 'name':<>, other vim specific }
        Raises an exception upon error or if not found
        """
        try:

            one = self._new_one_connection()
            template = one.template.info(int(flavor_id))
            if template is not None:
                return {'id': template.ID, 'name': template.NAME}
            raise vimconn.vimconnNotFoundException(
                "Flavor {} not found".format(flavor_id))
        except Exception as e:
            self.logger.error("get flavor " + str(flavor_id) + " error: " +
                              str(e))
            raise vimconn.vimconnException(e)
 def new_flavor(self, flavor_data):
     """Adds a tenant flavor to VIM
         Returns the flavor identifier"""
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         template_name = flavor_data["name"][:-4]
         name = 'NAME = "{}" '.format(template_name)
         cpu = 'CPU = "{}" '.format(flavor_data["vcpus"])
         memory = 'MEMORY = "{}" '.format(flavor_data["ram"])
         context = 'CONTEXT = [NETWORK = "YES",SSH_PUBLIC_KEY = "$USER[SSH_PUBLIC_KEY]" ] '
         graphics = 'GRAPHICS = [ LISTEN = "0.0.0.0", TYPE = "VNC" ] '
         sched_requeriments = 'CLUSTER_ID={}'.format(self.config["cluster"]["id"])
         template = name + cpu + memory + context + graphics + sched_requeriments
         template_id = oca.VmTemplate.allocate(client, template)
         return template_id
     except Exception as e:
         self.logger.error("Create new flavor error: " + str(e))
         raise vimconn.vimconnException(e)
Esempio n. 23
0
 def delete_vminstance(self, vm_id, created_items=None):
     """
     Removes a VM instance from VIM and each associate elements
     :param vm_id: VIM identifier of the VM, provided by method new_vminstance
     :param created_items: dictionary with extra items to be deleted. provided by method new_vminstance and/or method
         action_vminstance
     :return: None or the same vm_id. Raises an exception on fail
     """
     self.logger.debug('FOS delete_vminstance with args: {}'.format(
         locals()))
     fduid = created_items.get('fdu_id')
     try:
         self.fos_api.fdu.terminate(vm_id)
         self.fos_api.fdu.offload(fduid)
     except Exception as e:
         raise vimconn.vimconnException(
             "Error on deletting VM with id {}. Error {}".format(vm_id, e))
     return vm_id
 def delete_tenant(self, tenant_id):
     """Delete a tenant from VIM. Returns the old tenant identifier"""
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         group_list = oca.GroupPool(client)
         user_list = oca.UserPool(client)
         group_list.info()
         user_list.info()
         for group in group_list:
             if str(group.id) == str(tenant_id):
                 for user in user_list:
                     if str(user.name) == str(self.user):
                         self._delete_secondarygroup(user.id, group.id)
                         group.delete(client)
                 return None
         raise vimconn.vimconnNotFoundException("Group {} not found".format(tenant_id))
     except Exception as e:
         self.logger.error("Delete tenant " + str(tenant_id) + " error: " + str(e))
         raise vimconn.vimconnException(e)
 def get_network(self, net_id):
     """Obtain network details of network id"""
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         networkList = oca.VirtualNetworkPool(client)
         networkList.info()
         net = {}
         for network in networkList:
             if str(network.id) == str(net_id):
                 net['id'] = net_id
                 net['name'] = network.name
                 net['status'] = "ACTIVE"
                 break
         if net:
             return net
         else:
             raise vimconn.vimconnNotFoundException("Network {} not found".format(net_id))
     except Exception as e:
             self.logger.error("Get network " + str(net_id) + " error): " + str(e))
             raise vimconn.vimconnException(e)
    def get_image_list(self, filter_dict={}):
        """Obtain tenant images from VIM
        Filter_dict can be:
            name: image name
            id: image uuid
            checksum: image checksum
            location: image path
        Returns the image list of dictionaries:
            [{<the fields at Filter_dict plus some VIM specific>}, ...]
            List can be empty
        """
        # IMPORTANT!!!!! Modify python oca library path pool.py line 102

        try:
            client = oca.Client(self.user + ':' + self.passwd, self.url)
            image_pool = oca.ImagePool(client)
            image_pool.info()
            images = []
            if "name" in filter_dict.keys():
                image_name_filter = filter_dict["name"]
            else:
                image_name_filter = None
            if "id" in filter_dict.keys():
                image_id_filter = filter_dict["id"]
            else:
                image_id_filter = None
            for image in image_pool:
                match = False
                if str(image_name_filter) == str(image.name) and str(image.id) == str(image_id_filter):
                    match = True
                if image_name_filter is None and str(image.id) == str(image_id_filter):
                    match = True
                if image_id_filter is None and str(image_name_filter) == str(image.name):
                    match = True
                if match:
                    images_dict = {"name": image.name, "id": str(image.id)}
                    images.append(images_dict)
            return images
        except Exception as e:
            self.logger.error("Get image list error: " + str(e))
            raise vimconn.vimconnException(e)
 def delete_network(self, net_id):
     """Deletes a tenant network from VIM
         Returns the network identifier
     """
     try:
         # self.delete_bridge_host()
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         networkList = oca.VirtualNetworkPool(client)
         networkList.info()
         network_deleted = False
         for network in networkList:
             if str(network.id) == str(net_id):
                 oca.VirtualNetwork.delete(network)
                 network_deleted = True
         if network_deleted:
             return net_id
         else:
             raise vimconn.vimconnNotFoundException("Network {} not found".format(net_id))
     except Exception as e:
             self.logger.error("Delete network " + str(net_id) + "error: " + str(e))
             raise vimconn.vimconnException(e)
 def get_network_list(self, filter_dict={}):
     """Obtain tenant networks of VIM
     Filter_dict can be:
         name: network name
         id: network uuid
         public: boolean
         tenant_id: tenant
         admin_state_up: boolean
         status: 'ACTIVE'
     Returns the network list of dictionaries
     """
     try:
         client = oca.Client(self.user + ':' + self.passwd, self.url)
         networkList = oca.VirtualNetworkPool(client)
         networkList.info()
         response = []
         if "name" in filter_dict.keys():
             network_name_filter = filter_dict["name"]
         else:
             network_name_filter = None
         if "id" in filter_dict.keys():
             network_id_filter = filter_dict["id"]
         else:
             network_id_filter = None
         for network in networkList:
             match = False
             if network.name == network_name_filter and str(network.id) == str(network_id_filter):
                 match = True
             if network_name_filter is None and str(network.id) == str(network_id_filter):
                 match = True
             if network_id_filter is None and network.name == network_name_filter:
                 match = True
             if match:
                 net_dict = {"name": network.name, "id": str(network.id)}
                 response.append(net_dict)
         return response
     except Exception as e:
         self.logger.error("Get network list error: " + str(e))
         raise vimconn.vimconnException(e)
Esempio n. 29
0
    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):
        """Adds a VM instance to VIM
        Params:
            'start': (boolean) indicates if VM must start or created in pause mode.
            'image_id','flavor_id': image and flavor VIM id to use for the VM
            'net_list': list of interfaces, each one is a dictionary with:
                'name': (optional) name for the interface.
                'net_id': VIM network id where this interface must be connect to. Mandatory for type==virtual
                'vpci': (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
                'model': (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
                'mac_address': (optional) mac address to assign to this interface
                'ip_address': (optional) IP address to assign to this interface
                #TODO: CHECK if an optional 'vlan' parameter is needed for VIMs when type if VF and net_id is not provided,
                    the VLAN tag to be used. In case net_id is provided, the internal network vlan is used for tagging VF
                'type': (mandatory) can be one of:
                    'virtual', in this case always connected to a network of type 'net_type=bridge'
                     'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to a data/ptp network ot it
                           can created unconnected
                     'SR-IOV' or 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
                     'VFnotShared'(SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
                            are allocated on the same physical NIC
                'bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
                'port_security': (optional) If False it must avoid any traffic filtering at this interface. If missing
                                or True, it must apply the default VIM behaviour
                After execution the method will add the key:
                'vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this
                        interface. 'net_list' is modified
            'cloud_config': (optional) dictionary with:
                'key-pairs': (optional) list of strings with the public key to be inserted to the default user
                'users': (optional) list of users to be inserted, each item is a dict with:
                    'name': (mandatory) user name,
                    'key-pairs': (optional) list of strings with the public key to be inserted to the user
                'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
                    or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
                'config-files': (optional). List of files to be transferred. Each item is a dict with:
                    'dest': (mandatory) string with the destination absolute path
                    'encoding': (optional, by default text). Can be one of:
                        'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64'
                    'content' (mandatory): string with the content of the file
                    'permissions': (optional) string with file permissions, typically octal notation '0644'
                    'owner': (optional) file owner, string with the format 'owner:group'
                'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk)
            'disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
                'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
                'size': (mandatory) string with the size of the disk in GB
            availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required
            availability_zone_list: list of availability zones given by user in the VNFD descriptor.  Ignore if
                availability_zone_index is None
        Returns a tuple with the instance identifier and created_items or raises an exception on error
            created_items can be None or a dictionary where this method can include key-values that will be passed to
            the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc.
            Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
            as not present.
        """
        self.logger.debug('new_vminstance with rgs: {}'.format(locals()))
        fdu_uuid = '{}'.format(uuid.uuid4())

        flv = self.fos_api.flavor.get(flavor_id)
        img = self.fos_api.image.get(image_id)

        if flv is None:
            raise vimconn.vimconnNotFoundException(
                "Flavor {} not found at VIM".format(flavor_id))
        if img is None:
            raise vimconn.vimconnNotFoundException(
                "Image {} not found at VIM".format(image_id))

        created_items = {'fdu_id': '', 'node_id': '', 'connection_points': []}

        fdu_desc = {
            'name': name,
            'uuid': fdu_uuid,
            'computation_requirements': flv,
            'image': img,
            'hypervisor': self.hv,
            'migration_kind': 'LIVE',
            'interfaces': [],
            'io_ports': [],
            'connection_points': [],
            'depends_on': []
        }

        nets = []
        cps = []
        intf_id = 0
        for n in net_list:
            cp_id = '{}'.format(uuid.uuid4())
            n.update({'vim_id': cp_id})
            pair_id = n.get('net_id')

            cp_d = {'uuid': cp_id, 'pair_id': pair_id}
            intf_d = {
                'name': n.get('name', 'eth{}'.format(intf_id)),
                'is_mgmt': False,
                'if_type': 'INTERNAL',
                'virtual_interface': {
                    'intf_type': n.get('model', 'VIRTIO'),
                    'vpci': n.get('vpci', '0:0:0'),
                    'bandwidth': int(n.get('bw', 100))
                }
            }
            if n.get('mac_address', None) is not None:
                intf_d['mac_address'] = n['mac_address']

            created_items['connection_points'].append(cp_id)
            fdu_desc['connection_points'].append(cp_d)
            fdu_desc['interfaces'].append(intf_d)

            intf_id = intf_id + 1

        if cloud_config is not None:
            configuration = {'conf_type': 'CLOUD_INIT'}
            if cloud_config.get('user-data') is not None:
                configuration.update({'script': cloud_config.get('user-data')})
            if cloud_config.get('key-pairs') is not None:
                configuration.update(
                    {'ssh_keys': cloud_config.get('key-pairs')})

            if 'script' in configuration:
                fdu_desc.update({'configuration': configuration})

        ### NODE Selection ###
        # Infrastructure info
        #   nodes dict with
        #        uuid -> node uuid
        #        computational capabilities -> cpu, ram, and disk available
        #        hypervisors -> list of available hypervisors (eg. KVM, LXD, BARE)
        #
        #

        # UPDATING AVAILABLE INFRASTRUCTURE

        if len(self.nodes) == 0:
            nodes_id = self.fos_api.node.list()
        else:
            nodes_id = self.nodes
        nodes = []
        for n in nodes_id:
            n_info = self.fos_api.node.info(n)
            if n_info is None:
                continue
            n_plugs = []
            for p in self.fos_api.node.plugins(n):
                n_plugs.append(self.fos_api.plugin.info(n, p))

            n_cpu_number = len(n_info.get('cpu'))
            n_cpu_arch = n_info.get('cpu')[0].get('arch')
            n_cpu_freq = n_info.get('cpu')[0].get('frequency')
            n_ram = n_info.get('ram').get('size')
            n_disk_size = sorted(
                list(
                    filter(lambda x: 'sda' in x['local_address'],
                           n_info.get('disks'))),
                key=lambda k: k['dimension'])[-1].get('dimension')

            hvs = []
            for p in n_plugs:
                if p.get('type') == 'runtime':
                    hvs.append(p.get('name'))

            ni = {
                'uuid': n,
                'computational_capabilities': {
                    'cpu_count': n_cpu_number,
                    'cpu_arch': n_cpu_arch,
                    'cpu_freq': n_cpu_freq,
                    'ram_size': n_ram,
                    'disk_size': n_disk_size
                },
                'hypervisors': hvs
            }
            nodes.append(ni)

        # NODE SELECTION
        compatible_nodes = []
        for n in nodes:
            if fdu_desc.get('hypervisor') in n.get('hypervisors'):
                n_comp = n.get('computational_capabilities')
                f_comp = fdu_desc.get('computation_requirements')
                if f_comp.get('cpu_arch') == n_comp.get('cpu_arch'):
                    if f_comp.get('cpu_min_count') <= n_comp.get(
                            'cpu_count') and f_comp.get(
                                'ram_size_mb') <= n_comp.get('ram_size'):
                        if f_comp.get('disk_size_gb') <= n_comp.get(
                                'disk_size'):
                            compatible_nodes.append(n)

        if len(compatible_nodes) == 0:
            raise vimconn.vimconnConflictException("No available nodes at VIM")
        selected_node = random.choice(compatible_nodes)

        created_items.update({
            'fdu_id': fdu_uuid,
            'node_id': selected_node.get('uuid')
        })

        self.logger.debug('FOS Node {} FDU Descriptor: {}'.format(
            selected_node.get('uuid'), fdu_desc))

        try:
            self.fos_api.fdu.onboard(fdu_desc)
            instanceid = self.fos_api.fdu.instantiate(
                fdu_uuid, selected_node.get('uuid'))
            created_items.update({'instance_id': instanceid})

            self.fdu_node_map.update({instanceid: selected_node.get('uuid')})
            self.logger.debug('new_vminstance return: {}'.format(
                (fdu_uuid, created_items)))
            return (instanceid, created_items)
        except fimerrors.FIMAResouceExistingException as free:
            raise vimconn.vimconnConflictException(
                "VM already exists at VIM. Error {}".format(free))
        except Exception as e:
            raise vimconn.vimconnException(
                "Error while instantiating VM {}. Error {}".format(name, e))
Esempio n. 30
0
    def new_network(self,
                    net_name,
                    net_type,
                    ip_profile=None,
                    shared=False,
                    vlan=None):
        """Adds a tenant network to VIM
        Params:
            'net_name': name of the network
            'net_type': one of:
                'bridge': overlay isolated network
                'data':   underlay E-LAN network for Passthrough and SRIOV interfaces
                'ptp':    underlay E-LINE network for Passthrough and SRIOV interfaces.
            'ip_profile': is a dict containing the IP parameters of the network
                'ip_version': can be "IPv4" or "IPv6" (Currently only IPv4 is implemented)
                'subnet_address': ip_prefix_schema, that is X.X.X.X/Y
                'gateway_address': (Optional) ip_schema, that is X.X.X.X
                'dns_address': (Optional) comma separated list of ip_schema, e.g. X.X.X.X[,X,X,X,X]
                'dhcp_enabled': True or False
                'dhcp_start_address': ip_schema, first IP to grant
                'dhcp_count': number of IPs to grant.
            'shared': if this network can be seen/use by other tenants/organization
            'vlan': in case of a data or ptp net_type, the intended vlan tag to be used for the network
        Returns the network identifier on success or raises and exception on failure
        """
        self.logger.debug('new_network: {}'.format(locals()))
        if net_type in ['data', 'ptp']:
            raise vimconn.vimconnNotImplemented(
                '{} type of network not supported'.format(net_type))

        net_uuid = '{}'.format(uuid.uuid4())
        desc = {
            'uuid': net_uuid,
            'name': net_name,
            'net_type': 'ELAN',
            'is_mgmt': False
        }

        if ip_profile is not None:
            ip = {}
            if ip_profile.get('ip_version') == 'IPv4':
                ip_info = {}
                ip_range = self.__get_ip_range(
                    ip_profile.get('dhcp_start_address'),
                    ip_profile.get('dhcp_count'))
                dhcp_range = '{},{}'.format(ip_range[0], ip_range[1])
                ip.update({'subnet': ip_profile.get('subnet_address')})
                ip.update({'dns': ip_profile.get('dns', None)})
                ip.update(
                    {'dhcp_enable': ip_profile.get('dhcp_enabled', False)})
                ip.update({'dhcp_range': dhcp_range})
                ip.update({'gateway': ip_profile.get('gateway_address', None)})
                desc.update({'ip_configuration': ip_info})
            else:
                raise vimconn.vimconnNotImplemented(
                    'IPV6 network is not implemented at VIM')
            desc.update({'ip_configuration': ip})
        self.logger.debug(
            'VIM new_network args: {} - Generated Eclipse fog05 Descriptor {}'.
            format(locals(), desc))
        try:
            self.fos_api.network.add_network(desc)
        except fimerrors.FIMAResouceExistingException as free:
            raise vimconn.vimconnConflictException(
                "Network already exists at VIM. Error {}".format(free))
        except Exception as e:
            raise vimconn.vimconnException(
                "Unable to create network {}. Error {}".format(net_name, e))
            # No way from the current rest service to get the actual error, most likely it will be an already existing error
        return net_uuid
Esempio n. 31
0
    def new_flavor(self, flavor_data, change_name_if_used=True):
        '''Adds a tenant flavor to openstack VIM
        if change_name_if_used is True, it will change name in case of conflict, because it is not supported name repetition
        Returns the flavor identifier
        '''
        self.logger.debug("Adding flavor '%s'", str(flavor_data))
        retry=0
        max_retries=3
        name_suffix = 0
        name=flavor_data['name']
        while retry<max_retries:
            retry+=1
            try:
                self._reload_connection()
                if change_name_if_used:
                    #get used names
                    fl_names=[]
                    fl=self.nova.flavors.list()
                    for f in fl:
                        fl_names.append(f.name)
                    while name in fl_names:
                        name_suffix += 1
                        name = flavor_data['name']+"-" + str(name_suffix)
                        
                ram = flavor_data.get('ram',64)
                vcpus = flavor_data.get('vcpus',1)
                numa_properties=None

                extended = flavor_data.get("extended")
                if extended:
                    numas=extended.get("numas")
                    if numas:
                        numa_nodes = len(numas)
                        if numa_nodes > 1:
                            return -1, "Can not add flavor with more than one numa"
                        numa_properties = {"hw:numa_nodes":str(numa_nodes)}
                        numa_properties["hw:mem_page_size"] = "large"
                        numa_properties["hw:cpu_policy"] = "dedicated"
                        numa_properties["hw:numa_mempolicy"] = "strict"
                        for numa in numas:
                            #overwrite ram and vcpus
                            ram = numa['memory']*1024
                            if 'paired-threads' in numa:
                                vcpus = numa['paired-threads']*2
                                numa_properties["hw:cpu_threads_policy"] = "prefer"
                            elif 'cores' in numa:
                                vcpus = numa['cores']
                                #numa_properties["hw:cpu_threads_policy"] = "prefer"
                            elif 'threads' in numa:
                                vcpus = numa['threads']
                                numa_properties["hw:cpu_policy"] = "isolated"
                            for interface in numa.get("interfaces",() ):
                                if interface["dedicated"]=="yes":
                                    raise vimconn.vimconnException("Passthrough interfaces are not supported for the openstack connector", http_code=vimconn.HTTP_Service_Unavailable)
                                #TODO, add the key 'pci_passthrough:alias"="<label at config>:<number ifaces>"' when a way to connect it is available
                                
                #create flavor                 
                new_flavor=self.nova.flavors.create(name, 
                                ram, 
                                vcpus, 
                                flavor_data.get('disk',1),
                                is_public=flavor_data.get('is_public', True)
                            ) 
                #add metadata
                if numa_properties:
                    new_flavor.set_keys(numa_properties)
                return new_flavor.id
            except nvExceptions.Conflict as e:
                if change_name_if_used and retry < max_retries:
                    continue
                self._format_exception(e)
            #except nvExceptions.BadRequest as e:
            except (ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError) as e:
                self._format_exception(e)
Esempio n. 32
0
    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):
        """Adds a VM instance to VIM
            Params:
                'start': (boolean) indicates if VM must start or created in pause mode.
                'image_id','flavor_id': image and flavor VIM id to use for the VM
                'net_list': list of interfaces, each one is a dictionary with:
                    'name': (optional) name for the interface.
                    'net_id': VIM network id where this interface must be connect to. Mandatory for type==virtual
                    'vpci': (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
                    'model': (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
                    'mac_address': (optional) mac address to assign to this interface
                    'ip_address': (optional) IP address to assign to this interface
                    #TODO: CHECK if an optional 'vlan' parameter is needed for VIMs when type if VF and net_id is not provided,
                        the VLAN tag to be used. In case net_id is provided, the internal network vlan is used for tagging VF
                    'type': (mandatory) can be one of:
                        'virtual', in this case always connected to a network of type 'net_type=bridge'
                        'PCI-PASSTHROUGH' or 'PF' (passthrough): depending on VIM capabilities it can be connected to a data/ptp network ot it
                            can created unconnected
                        'SR-IOV' or 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
                        'VFnotShared'(SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
                                are allocated on the same physical NIC
                    'bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
                    'port_security': (optional) If False it must avoid any traffic filtering at this interface. If missing
                                    or True, it must apply the default VIM behaviour
                    After execution the method will add the key:
                    'vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this
                            interface. 'net_list' is modified
                'cloud_config': (optional) dictionary with:
                    'key-pairs': (optional) list of strings with the public key to be inserted to the default user
                    'users': (optional) list of users to be inserted, each item is a dict with:
                        'name': (mandatory) user name,
                        'key-pairs': (optional) list of strings with the public key to be inserted to the user
                    'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
                        or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
                    'config-files': (optional). List of files to be transferred. Each item is a dict with:
                        'dest': (mandatory) string with the destination absolute path
                        'encoding': (optional, by default text). Can be one of:
                            'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64'
                        'content' (mandatory): string with the content of the file
                        'permissions': (optional) string with file permissions, typically octal notation '0644'
                        'owner': (optional) file owner, string with the format 'owner:group'
                    'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk)
                'disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
                    'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
                    'size': (mandatory) string with the size of the disk in GB
                availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required
                availability_zone_list: list of availability zones given by user in the VNFD descriptor.  Ignore if
                    availability_zone_index is None
            Returns a tuple with the instance identifier and created_items or raises an exception on error
                created_items can be None or a dictionary where this method can include key-values that will be passed to
                the method delete_vminstance and action_vminstance. Can be used to store created ports, volumes, etc.
                Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
                as not present.
            """
        self.logger.debug(
            "new_vminstance input: image='{}' flavor='{}' nics='{}'".format(
                image_id, flavor_id, str(net_list)))
        try:
            one = self._new_one_connection()
            template_vim = one.template.info(int(flavor_id), True)
            disk_size = str(template_vim.TEMPLATE["DISK"]["SIZE"])

            one = self._new_one_connection()
            template_updated = ""
            for net in net_list:
                net_in_vim = one.vn.info(int(net["net_id"]))
                net["vim_id"] = str(net_in_vim.ID)
                network = 'NIC = [NETWORK = "{}",NETWORK_UNAME = "{}" ]'.format(
                    net_in_vim.NAME, net_in_vim.UNAME)
                template_updated += network

            template_updated += "DISK = [ IMAGE_ID = {},\n  SIZE = {}]".format(
                image_id, disk_size)

            if isinstance(cloud_config, dict):
                if cloud_config.get("key-pairs"):
                    context = 'CONTEXT = [\n  NETWORK = "YES",\n  SSH_PUBLIC_KEY = "'
                    for key in cloud_config["key-pairs"]:
                        context += key + '\n'
                    # if False:
                    #     context += '"\n  USERNAME = '******'"]'
                    template_updated += context

            vm_instance_id = one.template.instantiate(int(flavor_id), name,
                                                      False, template_updated)
            self.logger.info(
                "Instanciating in OpenNebula a new VM name:{} id:{}".format(
                    name, flavor_id))
            return str(vm_instance_id), None
        except pyone.OneNoExistsException as e:
            self.logger.error("Network with id " + str(e) + " not found: " +
                              str(e))
            raise vimconn.vimconnNotFoundException(e)
        except Exception as e:
            self.logger.error("Create new vm instance error: " + str(e))
            raise vimconn.vimconnException(e)
Esempio n. 33
0
    def new_vminstance(self,name,description,start,image_id,flavor_id,net_list):
        '''Adds a VM instance to VIM
        Params:
            start: indicates if VM must start or boot in pause mode. Ignored
            image_id,flavor_id: iamge and flavor uuid
            net_list: list of interfaces, each one is a dictionary with:
                name:
                net_id: network uuid to connect
                vpci: virtual vcpi to assign, ignored because openstack lack #TODO
                model: interface model, ignored #TODO
                mac_address: used for  SR-IOV ifaces #TODO for other types
                use: 'data', 'bridge',  'mgmt'
                type: 'virtual', 'PF', 'VF', 'VFnotShared'
                vim_id: filled/added by this function
                #TODO ip, security groups
        Returns the instance identifier
        '''
        self.logger.debug("Creating VM image '%s' flavor '%s' nics='%s'",image_id, flavor_id,str(net_list))
        try:
            metadata=[]
            net_list_vim=[]
            self._reload_connection()
            metadata_vpci={} #For a specific neutron plugin 
            for net in net_list:
                if not net.get("net_id"): #skip non connected iface
                    continue
                if net["type"]=="virtual":
                    net_list_vim.append({'net-id': net["net_id"]})
                    if "vpci" in net:
                        metadata_vpci[ net["net_id"] ] = [[ net["vpci"], "" ]]
                elif net["type"]=="PF":
                    self.logger.warn("new_vminstance: Warning, can not connect a passthrough interface ")
                    #TODO insert this when openstack consider passthrough ports as openstack neutron ports
                else: #VF
                    if "vpci" in net:
                        if "VF" not in metadata_vpci:
                            metadata_vpci["VF"]=[]
                        metadata_vpci["VF"].append([ net["vpci"], "" ])
                    port_dict={
                         "network_id": net["net_id"],
                         "name": net.get("name"),
                         "binding:vnic_type": "direct", 
                         "admin_state_up": True
                    }
                    if not port_dict["name"]:
                        port_dict["name"] = name
                    if net.get("mac_address"):
                        port_dict["mac_address"]=net["mac_address"]
                    #TODO: manage having SRIOV without vlan tag
                    #if net["type"] == "VFnotShared"
                    #    port_dict["vlan"]=0
                    new_port = self.neutron.create_port({"port": port_dict })
                    net["mac_adress"] = new_port["port"]["mac_address"]
                    net["vim_id"] = new_port["port"]["id"]
                    net["ip"] = new_port["port"].get("fixed_ips",[{}])[0].get("ip_address")
                    net_list_vim.append({"port-id": new_port["port"]["id"]})
            if metadata_vpci:
                metadata = {"pci_assignement": json.dumps(metadata_vpci)}
            
            self.logger.debug("name '%s' image_id '%s'flavor_id '%s' net_list_vim '%s' description '%s' metadata %s",
                              name, image_id, flavor_id, str(net_list_vim), description, str(metadata))
            
            security_groups   = self.config.get('security_groups')
            if type(security_groups) is str:
                security_groups = ( security_groups, )
            server = self.nova.servers.create(name, image_id, flavor_id, nics=net_list_vim, meta=metadata,
                                              security_groups   = security_groups,
                                              availability_zone = self.config.get('availability_zone'),
                                              key_name          = self.config.get('keypair'),
                                        ) #, description=description)
            
            
            #print "DONE :-)", server
            
#             #TODO   server.add_floating_ip("10.95.87.209")
#             #To look for a free floating_ip
#             free_floating_ip = None
#             for floating_ip in self.neutron.list_floatingips().get("floatingips", () ):
#                 if not floating_ip["port_id"]:
#                     free_floating_ip = floating_ip["floating_ip_address"]
#                     break
#             if free_floating_ip:
#                 server.add_floating_ip(free_floating_ip)
                
            
            return server.id
#        except nvExceptions.NotFound as e:
#            error_value=-vimconn.HTTP_Not_Found
#            error_text= "vm instance %s not found" % vm_id
        except (ksExceptions.ClientException, nvExceptions.ClientException, ConnectionError,
                neClient.exceptions.ConnectionFailed) as e:
            self._format_exception(e)
        except TypeError as e:
            raise vimconn.vimconnException(type(e).__name__ + ": "+  str(e), http_code=vimconn.HTTP_Bad_Request)
Esempio n. 34
0
 def action_vminstance(self, vm_id, action_dict):
     '''Send and action over a VM instance from VIM
     Returns the vm_id if the action was successfully sent to the VIM'''
     self.logger.debug("Action over VM '%s': %s", vm_id, str(action_dict))
     try:
         self._reload_connection()
         server = self.nova.servers.find(id=vm_id)
         if "start" in action_dict:
             if action_dict["start"]=="rebuild":  
                 server.rebuild()
             else:
                 if server.status=="PAUSED":
                     server.unpause()
                 elif server.status=="SUSPENDED":
                     server.resume()
                 elif server.status=="SHUTOFF":
                     server.start()
         elif "pause" in action_dict:
             server.pause()
         elif "resume" in action_dict:
             server.resume()
         elif "shutoff" in action_dict or "shutdown" in action_dict:
             server.stop()
         elif "forceOff" in action_dict:
             server.stop() #TODO
         elif "terminate" in action_dict:
             server.delete()
         elif "createImage" in action_dict:
             server.create_image()
             #"path":path_schema,
             #"description":description_schema,
             #"name":name_schema,
             #"metadata":metadata_schema,
             #"imageRef": id_schema,
             #"disk": {"oneOf":[{"type": "null"}, {"type":"string"}] },
         elif "rebuild" in action_dict:
             server.rebuild(server.image['id'])
         elif "reboot" in action_dict:
             server.reboot() #reboot_type='SOFT'
         elif "console" in action_dict:
             console_type = action_dict["console"]
             if console_type == None or console_type == "novnc":
                 console_dict = server.get_vnc_console("novnc")
             elif console_type == "xvpvnc":
                 console_dict = server.get_vnc_console(console_type)
             elif console_type == "rdp-html5":
                 console_dict = server.get_rdp_console(console_type)
             elif console_type == "spice-html5":
                 console_dict = server.get_spice_console(console_type)
             else:
                 raise vimconn.vimconnException("console type '{}' not allowed".format(console_type), 
                                                http_code=vimconn.HTTP_Bad_Request)
             try:
                 console_url = console_dict["console"]["url"]
                 #parse console_url
                 protocol_index = console_url.find("//")
                 suffix_index = console_url[protocol_index+2:].find("/") + protocol_index+2
                 port_index = console_url[protocol_index+2:suffix_index].find(":") + protocol_index+2
                 if protocol_index < 0 or port_index<0 or suffix_index<0:
                     raise vimconn.vimconnException("Unexpected response from VIM " + str(console_dict))
                 console_dict2={"protocol": console_url[0:protocol_index],
                               "server":   console_url[protocol_index+2 : port_index], 
                               "port":     int(console_url[port_index+1 : suffix_index]), 
                               "suffix":   console_url[suffix_index+1:] 
                               }
                 return console_dict2               
             except Exception as e:
                 raise vimconn.vimconnException("Unexpected response from VIM " + str(console_dict))
         
         return vm_id
     except (ksExceptions.ClientException, nvExceptions.ClientException, nvExceptions.NotFound) as e:
         self._format_exception(e)