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)
Exemple #2
0
    def subnet_sizes(self, availability_zones, cidr):
        """Calcualtes possible subnets given CIDR value of VPC
        """

        if availability_zones != 2 and availability_zones != 3:
            self.logger.debug("Number of AZs should be 2 or 3")
            raise vimconn.vimconnNotSupportedException("Number of AZs should be 2 or 3")

        netmasks = ('255.255.252.0', '255.255.254.0', '255.255.255.0', '255.255.255.128')
        ip = netaddr.IPNetwork(cidr)
        mask = ip.netmask

        if str(mask) not in netmasks:
            self.logger.debug("Netmask " + str(mask) + " not found")
            raise vimconn.vimconnNotFoundException("Netmask " + str(mask) + " not found")

        if availability_zones == 2:
            for n, netmask in enumerate(netmasks):
                if str(mask) == netmask:
                    subnets = list(ip.subnet(n + 24))
        else:
            for n, netmask in enumerate(netmasks):
                if str(mask) == netmask:
                    pub_net = list(ip.subnet(n + 24))
                    pri_subs = pub_net[1:]
                    pub_mask = pub_net[0].netmask
            pub_split = list(ip.subnet(26)) if (str(pub_mask) == '255.255.255.0') else list(ip.subnet(27))
            pub_subs = pub_split[:3]
            subnets = pub_subs + pri_subs

        return map(str, subnets)
Exemple #3
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)
Exemple #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)
Exemple #5
0
    def get_flavor_id_from_data(self, flavor_dict):
        """Obtain flavor id that match the flavor description
        Params:
            'flavor_dict': dictionary that contains:
                'disk': main hard disk in GB
                'ram': meomry in MB
                'vcpus': number of virtual cpus
                #TODO: complete parameters for EPA
        Returns the flavor_id or raises a vimconnNotFoundException
        """
        self.logger.debug('VIM get_flavor_id_from_data with args : {}'.format(
            locals()))

        try:
            flvs = self.fos_api.flavor.list()
        except Exception as e:
            raise vimconn.vimconnConnectionException(
                "VIM not reachable. Error {}".format(e))
        r = [
            x.get('uuid') for x in flvs
            if (x.get('cpu_min_count') == flavor_dict.get('vcpus')
                and x.get('ram_size_mb') == flavor_dict.get('ram')
                and x.get('storage_size_gb') == flavor_dict.get('disk'))
        ]
        if len(r) == 0:
            raise vimconn.vimconnNotFoundException("No flavor found")
        return r[0]
Exemple #6
0
    def get_flavor_id_from_data(self, flavor_dict):
        """Obtain flavor id that match the flavor description
        Params:
            'flavor_dict': dictionary that contains:
                'disk': main hard disk in GB
                'ram': memory in MB
                'vcpus': number of virtual cpus
                #todo: complete parameters for EPA
        Returns the flavor_id or raises a vimconnNotFoundException
        """

        self.logger.debug("Getting flavor id from data")
        try:
            flavor = None
            for key, values in self.flavor_info.iteritems():
                if (values["ram"], values["cpus"], values["disk"]) == (
                flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"]):
                    flavor = (key, values)
                    break
                elif (values["ram"], values["cpus"], values["disk"]) >= (
                flavor_dict["ram"], flavor_dict["vcpus"], flavor_dict["disk"]):
                    if not flavor:
                        flavor = (key, values)
                    else:
                        if (flavor[1]["ram"], flavor[1]["cpus"], flavor[1]["disk"]) >= (
                        values["ram"], values["cpus"], values["disk"]):
                            flavor = (key, values)
            if flavor:
                return flavor[0]
            raise vimconn.vimconnNotFoundException("Cannot find flavor with this flavor ID/Name")
        except Exception as e:
            self.format_vimconn_exception(e)
Exemple #7
0
 def get_image_id_from_path(self, path):
     '''Get the image id from image path in the VIM database. Returns the image_id 
     '''
     try:
         self._reload_connection()
         images = self.nova.images.list()
         for image in images:
             if image.metadata.get("location")==path:
                 return image.id
         raise vimconn.vimconnNotFoundException("image with location '{}' not found".format( path))
     except (ksExceptions.ClientException, nvExceptions.ClientException, gl1Exceptions.CommunicationError) as e: 
         self._format_exception(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)
Exemple #9
0
 def delete_flavor(self, flavor_id):
     """Deletes a tenant flavor from VIM identify by its id
     Returns the used id or raise an exception"""
     try:
         self.fos_api.flavor.remove(flavor_id)
     except fimerrors.FIMNotFoundException as fnfe:
         raise vimconn.vimconnNotFoundException(
             "Flavor {} not found at VIM (already deleted?). Error {}".
             format(flavor_id, fnfe))
     except Exception as e:
         raise vimconn.vimconnConnectionException(
             "VIM not reachable. Error {}".format(e))
     return flavor_id
Exemple #10
0
    def get_vminstance(self, vm_id):
        """Returns the VM instance information from VIM"""
        self.logger.debug('VIM get_vminstance with args: {}'.format(locals()))

        try:
            intsinfo = self.fos_api.fdu.instance_info(vm_id)
        except Exception as e:
            raise vimconn.vimconnConnectionException(
                "VIM not reachable. Error {}".format(e))
        if intsinfo is None:
            raise vimconn.vimconnNotFoundException(
                'VM with id {} not found!'.format(vm_id))
        return intsinfo
Exemple #11
0
 def get_flavor(self, flavor_id):
     """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
     """
     self.logger.debug('VIM get_flavor with args: {}'.format(locals()))
     try:
         r = self.fos_api.flavor.get(flavor_id)
     except Exception as e:
         raise vimconn.vimconnConnectionException(
             "VIM not reachable. Error {}".format(e))
     if r is None:
         raise vimconn.vimconnNotFoundException("Flavor not found at VIM")
     return {'id': r.get('uuid'), 'name': r.get('name'), 'fos': r}
Exemple #12
0
    def get_flavor(self, flavor_id):
        """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
        """

        self.logger.debug("Getting instance type")
        try:
            if flavor_id in self.flavor_info:
                return self.flavor_info[flavor_id]
            else:
                raise vimconn.vimconnNotFoundException("Cannot find flavor with this flavor ID/Name")
        except Exception as e:
            self.format_vimconn_exception(e)
Exemple #13
0
 def _format_exception(self, exception):
     '''Transform a keystone, nova, neutron  exception into a vimconn exception'''
     if isinstance(exception, (HTTPException, gl1Exceptions.HTTPException, gl1Exceptions.CommunicationError,
                               ConnectionError, ksExceptions.ConnectionError, neExceptions.ConnectionFailed,
                               neClient.exceptions.ConnectionFailed)):
         raise vimconn.vimconnConnectionException(type(exception).__name__ + ": " + str(exception))            
     elif isinstance(exception, (nvExceptions.ClientException, ksExceptions.ClientException, 
                                 neExceptions.NeutronException, nvExceptions.BadRequest)):
         raise vimconn.vimconnUnexpectedResponse(type(exception).__name__ + ": " + str(exception))
     elif isinstance(exception, (neExceptions.NetworkNotFoundClient, nvExceptions.NotFound)):
         raise vimconn.vimconnNotFoundException(type(exception).__name__ + ": " + str(exception))
     elif isinstance(exception, nvExceptions.Conflict):
         raise vimconn.vimconnConflictException(type(exception).__name__ + ": " + str(exception))
     else: # ()
         raise vimconn.vimconnConnectionException(type(exception).__name__ + ": " + str(exception))
Exemple #14
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
     """
     self.logger.debug('get_network: {}'.format(net_id))
     res = self.get_network_list(filter_dict={'id': net_id})
     if len(res) == 0:
         raise vimconn.vimconnNotFoundException(
             "Network {} not found at VIM".format(net_id))
     return res[0]
Exemple #15
0
 def get_image_id_from_path(self, path):
     """Get the image id from image path in the VIM database.
        Returns the image_id or raises a vimconnNotFoundException
     """
     self.logger.debug('VIM get_image_id_from_path with args: {}'.format(
         locals()))
     try:
         imgs = self.fos_api.image.list()
     except Exception as e:
         raise vimconn.vimconnConnectionException(
             "VIM not reachable. Error {}".format(e))
     res = [x.get('uuid') for x in imgs if x.get('uri') == path]
     if len(res) == 0:
         raise vimconn.vimconnNotFoundException(
             "Image with this path was not found")
     return res[0]
Exemple #16
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
 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)
Exemple #18
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 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 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)
 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 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)
Exemple #23
0
 def get_network(self, net_id):
     '''Obtain details of network from VIM
     Returns the network information from a network id'''
     self.logger.debug(" Getting tenant network %s from VIM", net_id)
     filter_dict={"id": net_id}
     net_list = self.get_network_list(filter_dict)
     if len(net_list)==0:
         raise vimconn.vimconnNotFoundException("Network '{}' not found".format(net_id))
     elif len(net_list)>1:
         raise vimconn.vimconnConflictException("Found more than one network with this criteria")
     net = net_list[0]
     subnets=[]
     for subnet_id in net.get("subnets", () ):
         try:
             subnet = self.neutron.show_subnet(subnet_id)
         except Exception as e:
             self.logger.error("osconnector.get_network(): Error getting subnet %s %s" % (net_id, str(e)))
             subnet = {"id": subnet_id, "fault": str(e)}
         subnets.append(subnet)
     net["subnets"] = subnets
     return net
Exemple #24
0
 def action_vminstance(self, vm_id, action_dict, created_items={}):
     """
     Send and action over a VM instance. Returns created_items if the action was successfully sent to the VIM.
     created_items is a dictionary with items that
     :param vm_id: VIM identifier of the VM, provided by method new_vminstance
     :param action_dict: dictionary with the action to perform
     :param created_items: provided by method new_vminstance is a dictionary with key-values that will be passed to
         the method delete_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. This
         method can modify this value
     :return: None, or a console dict
     """
     self.logger.debug('VIM action_vminstance with args: {}'.format(
         locals()))
     nid = self.fdu_node_map.get(vm_id)
     if nid is None:
         raise vimconn.vimconnNotFoundException('No node for this VM')
     try:
         fdu_info = self.fos_api.fdu.instance_info(vm_id)
         if "start" in action_dict:
             if fdu_info.get('status') == 'CONFIGURE':
                 self.fos_api.fdu.start(vm_id)
             elif fdu_info.get('status') == 'PAUSE':
                 self.fos_api.fdu.resume(vm_id)
             else:
                 raise vimconn.vimconnConflictException(
                     "Cannot start from this state")
         elif "pause" in action_dict:
             if fdu_info.get('status') == 'RUN':
                 self.fos_api.fdu.pause(vm_id)
             else:
                 raise vimconn.vimconnConflictException(
                     "Cannot pause from this state")
         elif "resume" in action_dict:
             if fdu_info.get('status') == 'PAUSE':
                 self.fos_api.fdu.resume(vm_id)
             else:
                 raise vimconn.vimconnConflictException(
                     "Cannot resume from this state")
         elif "shutoff" in action_dict or "shutdown" or "forceOff" in action_dict:
             if fdu_info.get('status') == 'RUN':
                 self.fos_api.fdu.stop(vm_id)
             else:
                 raise vimconn.vimconnConflictException(
                     "Cannot shutoff from this state")
         elif "terminate" in action_dict:
             if fdu_info.get('status') == 'RUN':
                 self.fos_api.fdu.stop(vm_id)
                 self.fos_api.fdu.clean(vm_id)
                 self.fos_api.fdu.undefine(vm_id)
                 # self.fos_api.fdu.offload(vm_id)
             elif fdu_info.get('status') == 'CONFIGURE':
                 self.fos_api.fdu.clean(vm_id)
                 self.fos_api.fdu.undefine(vm_id)
                 # self.fos_api.fdu.offload(vm_id)
             elif fdu_info.get('status') == 'PAUSE':
                 self.fos_api.fdu.resume(vm_id)
                 self.fos_api.fdu.stop(vm_id)
                 self.fos_api.fdu.clean(vm_id)
                 self.fos_api.fdu.undefine(vm_id)
                 # self.fos_api.fdu.offload(vm_id)
             else:
                 raise vimconn.vimconnConflictException(
                     "Cannot terminate from this state")
         elif "rebuild" in action_dict:
             raise vimconnNotImplemented("Rebuild not implememnted")
         elif "reboot" in action_dict:
             if fdu_info.get('status') == 'RUN':
                 self.fos_api.fdu.stop(vm_id)
                 self.fos_api.fdu.start(vm_id)
             else:
                 raise vimconn.vimconnConflictException(
                     "Cannot reboot from this state")
     except Exception as e:
         raise vimconn.vimconnConnectionException(
             "VIM not reachable. Error {}".format(e))
Exemple #25
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))
Exemple #26
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)
Exemple #27
0
    def __init__(self,
                 uuid,
                 name,
                 tenant_id,
                 tenant_name,
                 url,
                 url_admin=None,
                 user=None,
                 passwd=None,
                 log_level=None,
                 config={},
                 persistent_info={}):
        """ Params: uuid - id asigned to this VIM
                name - name assigned to this VIM, can be used for logging
                tenant_id - ID to be used for tenant
                tenant_name - name of tenant to be used VIM tenant to be used
                url_admin - optional, url used for administrative tasks
                user - credentials of the VIM user
                passwd - credentials of the VIM user
                log_level - if must use a different log_level than the general one
                config - dictionary with misc VIM information
                    region_name - name of region to deploy the instances
                    vpc_cidr_block - default CIDR block for VPC
                    security_groups - default security group to specify this instance
                persistent_info - dict where the class can store information that will be available among class
                    destroy/creation cycles. This info is unique per VIM/credential. At first call it will contain an
                    empty dict. Useful to store login/tokens information for speed up communication
        """

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

        self.persistent_info = persistent_info
        self.a_creds = {}
        if user:
            self.a_creds['aws_access_key_id'] = user
        else:
            raise vimconn.vimconnAuthException("Username is not specified")
        if passwd:
            self.a_creds['aws_secret_access_key'] = passwd
        else:
            raise vimconn.vimconnAuthException("Password is not specified")
        if 'region_name' in config:
            self.region = config.get('region_name')
        else:
            raise vimconn.vimconnNotFoundException(
                "AWS region_name is not specified at config")

        self.vpc_data = {}
        self.subnet_data = {}
        self.conn = None
        self.conn_vpc = None
        self.account_id = None

        self.vpc_id = self.get_tenant_list()[0]['id']
        # we take VPC CIDR block if specified, otherwise we use the default CIDR
        # block suggested by AWS while creating instance
        self.vpc_cidr_block = '10.0.0.0/24'

        if tenant_id:
            self.vpc_id = tenant_id
        if 'vpc_cidr_block' in config:
            self.vpc_cidr_block = config['vpc_cidr_block']

        self.security_groups = None
        if 'security_groups' in config:
            self.security_groups = config['security_groups']

        self.key_pair = None
        if 'key_pair' in config:
            self.key_pair = config['key_pair']

        self.flavor_info = None
        if 'flavor_info' in config:
            flavor_data = config.get('flavor_info')
            if isinstance(flavor_data, str):
                try:
                    with open(flavor_data[1:], 'r') as stream:
                        self.flavor_info = yaml.load(stream)
                except yaml.YAMLError as e:
                    self.flavor_info = None
                    raise vimconn.vimconnException(
                        "Bad format at file '{}': {}".format(
                            flavor_data[1:], e))
                except IOError as e:
                    raise vimconn.vimconnException(
                        "Error reading file '{}': {}".format(
                            flavor_data[1:], e))
            elif isinstance(flavor_data, dict):
                self.flavor_info = flavor_data

        self.logger = logging.getLogger('openmano.vim.aws')
        if log_level:
            self.logger.setLevel(getattr(logging, log_level))