+ @staticmethod
+ def _create_mimemultipart(content_list):
+ """Creates a MIMEmultipart text combining the content_list
+ :param content_list: list of text scripts to be combined
+ :return: str of the created MIMEmultipart. If the list is empty returns None, if the list contains only one
+ element MIMEmultipart is not created and this content is returned
+ """
+ if not content_list:
+ return None
+ elif len(content_list) == 1:
+ return content_list[0]
+ combined_message = MIMEMultipart()
+ for content in content_list:
+ if content.startswith('#include'):
+ format = 'text/x-include-url'
+ elif content.startswith('#include-once'):
+ format = 'text/x-include-once-url'
+ elif content.startswith('#!'):
+ format = 'text/x-shellscript'
+ elif content.startswith('#cloud-config'):
+ format = 'text/cloud-config'
+ elif content.startswith('#cloud-config-archive'):
+ format = 'text/cloud-config-archive'
+ elif content.startswith('#upstart-job'):
+ format = 'text/upstart-job'
+ elif content.startswith('#part-handler'):
+ format = 'text/part-handler'
+ elif content.startswith('#cloud-boothook'):
+ format = 'text/cloud-boothook'
+ else: # by default
+ format = 'text/x-shellscript'
+ sub_message = MIMEText(content, format, sys.getdefaultencoding())
+ combined_message.attach(sub_message)
+ return combined_message.as_string()
+
+ def __wait_for_vm(self, vm_id, status):
+ """wait until vm is in the desired status and return True.
+ If the VM gets in ERROR status, return false.
+ If the timeout is reached generate an exception"""
+ elapsed_time = 0
+ while elapsed_time < server_timeout:
+ vm_status = self.nova.servers.get(vm_id).status
+ if vm_status == status:
+ return True
+ if vm_status == 'ERROR':
+ return False
+ time.sleep(1)
+ elapsed_time += 1
+
+ # if we exceeded the timeout rollback
+ if elapsed_time >= server_timeout:
+ raise vimconn.vimconnException('Timeout waiting for instance ' + vm_id + ' to get ' + status,
+ http_code=vimconn.HTTP_Request_Timeout)
+
+ def _get_openstack_availablity_zones(self):
+ """
+ Get from openstack availability zones available
+ :return:
+ """
+ try:
+ openstack_availability_zone = self.nova.availability_zones.list()
+ openstack_availability_zone = [str(zone.zoneName) for zone in openstack_availability_zone
+ if zone.zoneName != 'internal']
+ return openstack_availability_zone
+ except Exception as e:
+ return None
+
+ def _set_availablity_zones(self):
+ """
+ Set vim availablity zone
+ :return:
+ """
+
+ if 'availability_zone' in self.config:
+ vim_availability_zones = self.config.get('availability_zone')
+ if isinstance(vim_availability_zones, str):
+ self.availability_zone = [vim_availability_zones]
+ elif isinstance(vim_availability_zones, list):
+ self.availability_zone = vim_availability_zones
+ else:
+ self.availability_zone = self._get_openstack_availablity_zones()
+
+ def _get_vm_availability_zone(self, availability_zone_index, availability_zone_list):
+ """
+ Return thge availability zone to be used by the created VM.
+ :return: The VIM availability zone to be used or None
+ """
+ if availability_zone_index is None:
+ if not self.config.get('availability_zone'):
+ return None
+ elif isinstance(self.config.get('availability_zone'), str):
+ return self.config['availability_zone']
+ else:
+ # TODO consider using a different parameter at config for default AV and AV list match
+ return self.config['availability_zone'][0]
+
+ vim_availability_zones = self.availability_zone
+ # check if VIM offer enough availability zones describe in the VNFD
+ if vim_availability_zones and len(availability_zone_list) <= len(vim_availability_zones):
+ # check if all the names of NFV AV match VIM AV names
+ match_by_index = False
+ for av in availability_zone_list:
+ if av not in vim_availability_zones:
+ match_by_index = True
+ break
+ if match_by_index:
+ return vim_availability_zones[availability_zone_index]
+ else:
+ return availability_zone_list[availability_zone_index]
+ else:
+ raise vimconn.vimconnConflictException("No enough availability zones at VIM for this deployment")
+
+ 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):