Beispiel #1
0
 def run(self, *args, **kwargs):
     operation_params = json.loads(self.db_operation.params)
     region = operation_params.get('region')
     if not region:
         return self.abort_operation()
     nc = nova_client(
         api_session=IdentityAdminApi(request_session=AUTH_CACHE).session,
         region_name=region)
     try:
         instance = nc.servers.get(
             server={'id': self.db_operation.primary_object_id})
     except (Exception, NotFound):
         instance = None
     if not instance:
         resource_usage_log = ResourceUsageLog.objects.filter(
             resource_uuid=self.db_operation.primary_object_id).order_by(
                 'start').last()
         if not resource_usage_log:
             return self.abort_operation()
         if not resource_usage_log.end:
             timestamp = utcnow().isoformat()
             LOG.info(
                 'Instance delete operation successfully set the resource usage log end date'
             )
             resource_usage_log.end = timestamp
             resource_usage_log.save()
             return self.mark_as_completed()
         else:
             LOG.info(
                 'Instance related resource usage log was already ended by OS messages'
             )
             return self.mark_as_completed()
Beispiel #2
0
def delete_project_security_groups(api_session,
                                   project_id,
                                   region=None,
                                   instances_list: Optional[List] = None):
    neutron_cl = neutron_client(api_session, region_name=region)
    nova_c = nova_client(api_session=api_session, region_name=region)
    # wait for all instances to be gone first
    if instances_list:
        for instance_id in instances_list:
            wait_for_instance_deleted(device_id=instance_id, nova_c=nova_c)

    try:
        security_groups = neutron_cl.list_security_groups(
            fields=['id',
                    'name'], tenant_id=project_id).get('security_groups', [])
        for security_group in security_groups:
            if security_group['name'] != 'default':
                try:
                    neutron_cl.delete_security_group(security_group['id'])
                except Conflict as e:
                    LOG.exception(
                        e
                    )  # should not get here because we waited for instances to disappear above
    except Exception as e:
        LOG.exception(e)
Beispiel #3
0
    def compute_api(self):
        """
        :rtype: novaclient.v2.client.Client
        """
        assert self.api_session is not None, 'Unable to use compute_api without a Keystoneauth session'

        return nova_client(api_session=self.api_session,
                           region_name=self.region_name)
Beispiel #4
0
 def nova_api(self):
     """
     :rtype: novaclient.v2.client.Client
     """
     assert self.api_session is not None, 'Unable to use nova_api without an api_session!'
     # TODO(Marius): refactor this class, the way it uses the nova client
     return nova_client(api_session=self.api_session,
                        region_name=self.db_flavor.region.id)
Beispiel #5
0
    def create(self,
               name,
               image,
               flavor,
               admin_pass,
               nics,
               region_name,
               user_data,
               key_name=None,
               key_content=None,
               block_device_mapping=None,
               block_device_mapping_v2=None):
        """
        :type name: str or unicode, the instance name
        :type image: str or unicode, the flavor id
        :type flavor: str or unicode
        :type admin_pass: str or unicode, the root/admin password for the instance
        :type nics: dict, network interfaces for the instance
        :type key_name: str or unicode, the ssh keypair name
        :type region_name: str or unicode
        :type key_content: str or unicode
        :type block_device_mapping: dict
        :type block_device_mapping_v2: list of dicts

        :rtype: :class:`novaclient.v2.servers.Server`
        """
        # Create the ssh keypair in Nova if needed
        if key_name and key_content:
            kp = Keypairs(api_session=self.api_session,
                          region_name=region_name)
            nova_key_name = kp.create_if_missing(name=key_name,
                                                 public_key=key_content)
        else:
            nova_key_name = None
        # Create the default security group if Needed
        # TODO(tomo): Try to deal with the default security group in another way
        sgid = create_security_group_if_missing(api_session=self.api_session,
                                                region=region_name)

        nc = nova_client(api_session=self.api_session, region_name=region_name)

        params = dict(name=name,
                      image=image,
                      flavor=flavor,
                      nics=nics,
                      security_groups=[sgid],
                      key_name=nova_key_name,
                      block_device_mapping=block_device_mapping,
                      block_device_mapping_v2=block_device_mapping_v2)
        if plugin_settings.force_config_drive_for_instance_creation:
            params['config_drive'] = True
        if admin_pass:
            params['admin_pass'] = admin_pass
        if user_data:
            params['userdata'] = user_data
        return nc.servers.create(**params)
Beispiel #6
0
    def admin_api(self):
        """
        :rtype: novaclient.v2.client.Client
        """
        admin_session = self._get_admin_session()
        assert admin_session is not None, 'Unable to use admin_api without a Keystoneauth session'

        return nova_client(api_session=admin_session,
                           region_name=self.instance.region,
                           extensions=True)
Beispiel #7
0
    def nova_admin_api(self):
        """
        :rtype: novaclient.v2.client.Client
        """
        assert self.admin_session is not None, 'Unable to use admin_api without a Keystoneauth session'

        return nova_client(api_session=self.admin_session,
                           region_name=self.region,
                           endpoint_type=self.interface,
                           extensions=True)
Beispiel #8
0
 def _get_hypervisor_host_name(self, instance_id: str,
                               region: str) -> Optional[str]:
     """gets host name from 'OS-EXT-SRV-ATTR:host' attribute found on instances"""
     nc = nova_client(api_session=self.admin_api_session,
                      region_name=region)
     try:
         nc_instance = nc.servers.get(instance_id)
     except Exception as e:
         LOG.error(str(e))
         return None
     return getattr(nc_instance, 'OS-EXT-SRV-ATTR:host', None)
Beispiel #9
0
def sync_instances(region_id=None):
    ih = InstanceSyncHandler()
    nc = nova_client(api_session=get_keystone_admin().session, region_name=region_id)
    try:
        for instance in nc.servers.list(detailed=True, search_opts={'all_tenants': '1'}):
            ih.create_or_update(instance, region=region_id, timestamp=timestamp)
    except EndpointNotFound as e:
        LOG.error(str(e))
        return
    version = ih.get_version(timestamp)
    delete_filter = {'{}__lt'.format(ih.version_field): version, 'region': region_id}
    ih.model_class.objects.filter(**delete_filter).delete()
Beispiel #10
0
    def get_hypervisors(self, region=None):
        """
        :param region: Openstack region name
        :return:
        """
        try:
            nc = nova_client(api_session=self.api_session, region_name=region)
            hypervisors = nc.hypervisors.list()
        except EndpointNotFound:

            return []
        else:
            return hypervisors
Beispiel #11
0
 def perform_create(self, serializer):
     os_api = self.get_os_api(
         request=self.request)  # type: [OSApi, OSAdminApi]
     serialized_data = copy.deepcopy(serializer.validated_data)
     cluster_template_id = serialized_data.get('cluster_template_id')
     keypair_name = serialized_data.pop('keypair')
     keypair = PublicKey.objects.filter(user=self.request.user,
                                        name=keypair_name).first()
     if not keypair:
         if self.request.user.is_staff:
             msg = _('Provided keypair was not found or you do not own it.')
         else:
             msg = _('Provided keypair was not found.')
         raise APIBadRequest(msg)
     keypair_name_formatted = '{}_{}'.format(
         keypair_name, self.get_project_id(request=self.request))
     if not cluster_template_id:
         raise APIBadRequest(_('You need to provide a cluster template'))
     cluster_template = ClusterTemplate.objects.filter(
         id=cluster_template_id).first()
     if not cluster_template:
         raise APIBadRequest(
             _('Provided cluster template cannot be found anymore'))
     nc = nova_client(api_session=identity.IdentityAdminApi().session,
                      region_name=cluster_template.region)
     try:
         nc.keypairs.create(name=keypair_name_formatted,
                            public_key=newlines_substract(
                                keypair.public_key))
     except Conflict:
         # Key was created before, use it
         try:
             return os_api.clusters.create(
                 region_id=cluster_template.region,
                 keypair=keypair_name_formatted,
                 **serialized_data,
             )
         except Exception as e:
             raise APIBadRequest(str(e))
     except Exception as e:
         raise APIBadRequest(str(e))
     try:
         return os_api.clusters.create(
             region_id=cluster_template.region,
             keypair=keypair_name_formatted,
             **serialized_data,
         )
     except Exception as e:
         raise APIBadRequest(str(e))
Beispiel #12
0
def delete_openstack_instance(self,
                              instance_id,
                              region,
                              project_id,
                              user_id: Optional[int] = None):
    del self  # unused

    project = Project.with_admin_session(project_id, cache=AUTH_CACHE)
    nc = nova_client(api_session=project.api_session,
                     region_name=region,
                     extensions=True)
    try:
        user = AppUser.objects.filter(id=user_id).first()
        db_instance = ModelInstance.objects.filter(id=instance_id).first()
        nc.servers.delete(server=instance_id)
        if user and db_instance:
            if user.is_staff:
                staff_signals.staff_delete_instance.send(
                    sender=__name__,
                    user=user,
                    user_id=user.id,
                    instance_name=db_instance.name,
                    instance_id=instance_id,
                    username=user.username)
            else:
                user_signals.user_delete_instance.send(
                    sender=__name__,
                    user=user,
                    user_id=user.id,
                    instance_name=db_instance.name,
                    instance_id=instance_id,
                    username=user.username)
    except nova_exceptions.NotFound:
        ModelInstance.objects.filter(id=instance_id).delete()
    else:
        Operation.objects.create(operation_type=InstanceDeletion.name,
                                 primary_object_id=instance_id,
                                 params=json.dumps({
                                     'region': region,
                                 }))
Beispiel #13
0
def get_current_cores():
    if 'fleio.openstack' not in settings.INSTALLED_APPS:
        return 0

    from fleio.openstack.api.identity import IdentityAdminApi
    from fleio.openstack.api.nova import nova_client
    from fleio.openstack.models import OpenstackRegion

    physical_cores = 0
    for region in OpenstackRegion.objects.all():
        try:
            client = nova_client(api_session=IdentityAdminApi().session,
                                 region_name=region.id)
            for virtual_node in client.hypervisors.list():
                cpu_info = virtual_node.cpu_info
                if isinstance(cpu_info, str):
                    cpu_info = json.loads(cpu_info)
                physical_cores += int(cpu_info['topology']['cores'])
        except (ClientException, ConnectTimeout, Unauthorized, ConnectFailure,
                TypeError, JSONDecodeError, DiscoveryFailure):
            raise exceptions.APIException()
        except EndpointNotFound:
            # region not available
            LOG.error(
                'Region not found when attempting to get number of cores for region {}, ignoring'
                .format(region.id), )
        except ConfigException:
            # configuration error
            LOG.exception(
                'Invalid configuration when attempting to get number of cores for region {}, ignoring'
                .format(region.id), )
            # region not available
        except Exception as e:
            del e  # unused
            LOG.exception(
                'Exception when attempting to get number of cores for region {}, ignoring'
                .format(region.id), )
    return physical_cores
Beispiel #14
0
    def create(self,
               name,
               ram,
               vcpus,
               disk,
               flavorid,
               ephemeral=0,
               swap=0,
               rxtx_factor=1.0,
               is_public=True,
               region=None):

        novaclient = nova_client(api_session=self.api_session,
                                 region_name=region)

        return novaclient.flavors.create(name,
                                         ram,
                                         vcpus,
                                         disk,
                                         flavorid=flavorid,
                                         ephemeral=ephemeral,
                                         swap=swap,
                                         rxtx_factor=rxtx_factor,
                                         is_public=is_public)
Beispiel #15
0
def sync_flavors(region_id=None):
    def _get_int_or_zero(value):
        """Convert to int or return 0 if unable to convert."""
        try:
            int_value = int(value)
        except ValueError:
            int_value = 0
        return int_value

    def _update_flavor(dbf, openstack_flavor):
        dbf.name = openstack_flavor.name
        dbf.vcpus = openstack_flavor.vcpus
        dbf.root_gb = _get_int_or_zero(openstack_flavor.disk)
        dbf.memory_mb = _get_int_or_zero(openstack_flavor.ram)
        dbf.swap = _get_int_or_zero(openstack_flavor.swap)
        dbf.is_public = openstack_flavor.is_public
        dbf.region_id = region_id
        dbf.disabled = getattr(openstack_flavor, 'OS-FLV-DISABLED:disabled', False)
        dbf.ephemeral_gb = _get_int_or_zero(openstack_flavor.ephemeral)
        dbf.deleted = False
        properties = openstack_flavor.get_keys()
        dbf.properties = json.dumps(properties)
        if not dbf.description:
            dbf.description = openstack_flavor.name
        dbf.save()

    # Get flavors from API
    try:
        api_flavors = nova_client(api_session=get_keystone_admin().session, region_name=region_id).\
            flavors.list(is_public=None)
    except EndpointNotFound as e:
        LOG.error(str(e))
        return
    existing_flavors = []
    for f in api_flavors:
        try:
            db_flv = OpenstackInstanceFlavor.objects.get(id=f.id)
            existing_flavors.append(db_flv.id)
        except OpenstackInstanceFlavor.DoesNotExist:
            LOG.info('Attempting to create missing flavor: %s ' % f.name)
            # Get the region object in DB
            try:
                db_flv = OpenstackInstanceFlavor.objects.create(id=f.id,
                                                                name=f.name,
                                                                memory_mb=_get_int_or_zero(f.ram),
                                                                vcpus=f.vcpus,
                                                                swap=_get_int_or_zero(f.swap),
                                                                root_gb=f.disk,
                                                                ephemeral_gb=_get_int_or_zero(f.ephemeral),
                                                                is_public=f.is_public,
                                                                disabled=getattr(f, 'OS-FLV-DISABLED:disabled', False),
                                                                region_id=region_id,
                                                                show_in_fleio=True,
                                                                description=f.name,
                                                                properties=json.dumps(f.get_keys()))
                existing_flavors.append(db_flv.id)
            except Exception as e:
                LOG.error('Unable to create flavor %s: %s' % (f.name, e))
            # Go to the next flavor if not found.
            continue

        # If found, update it's records:
        _update_flavor(db_flv, f)
    # Remove missing flavors from region
    OpenstackInstanceFlavor.objects.exclude(id__in=existing_flavors).filter(region__id=region_id).delete()
Beispiel #16
0
def run_backup(time_to_execute):
    # TODO(MARIUS): implement command line arguments (recognisable flags like --force/-f)
    # TODO(MARIUS): don't backup schedules from db that have already been executed (they pass the filter condition now)
    # TODO(MARIUS): check backup types and execute the backups based on that, for accuracy
    """
    :param time_to_execute: The time at which the procedure will be executed.

    Scenario 1 (auto-run):
        - an external automatic process (cron for linux, windows task scheduler for windows) will be set to execute this
          script, in which :param time_to_execute: will be the time that the external process was set to run
          e.g (5:00 AM, daily / weekly / etc.)

    Scenario 2 (manual-run):
        - script is run manually, in which case :param time_to_execute: will be the time at which the script is executed

    All backups that are scheduled BEFORE the :param time_to_execute: are going to be executed.
    """
    # default_session = admin_session()
    backups_to_execute = OpenStackBackupSchedule.objects.filter(
        run_at__lt=time_to_execute)
    total_backups = len(backups_to_execute)
    backups_executed = 0
    backups_failed = []
    session_map = dict(
        # stores sessions based on project_id
    )
    for backup in backups_to_execute:
        instance_region = backup.instance.region
        project_id = backup.instance.project_id
        # use the session related to the instance project_id
        new_session = session_map.get(project_id, None)
        if not new_session:
            new_session = custom_session(project_id=project_id)
            session_map[
                project_id] = new_session  # store the session in case we need it later
        gc = glance_client(api_session=new_session,
                           region_name=instance_region)
        nc = nova_client(api_session=new_session, region_name=instance_region)
        nc.servers.backup(server=backup.instance.id,
                          backup_name=backup.backup_name,
                          backup_type=backup.backup_type,
                          rotation=backup.rotation)
        if len(list(gc.images.list(filters={'name': backup.backup_name}))) > 0:
            backups_executed += 1
        else:
            backups_failed.append(backup.instance.id)
            logger.error(e)
            logger.info(
                'Cannot perform backup on instance {}, instance currently under a task state.'
                .format(backup.instance.id))
    time_to_execute = time_to_execute.strftime('%Y-%m-%d %H:%M:%S')

    if not backups_failed:
        msg = _(
            '{executed} out of {total} backups were created successfully before {time_to_execute}'
        ).format(executed=backups_executed,
                 total=total_backups,
                 time_to_execute=time_to_execute)
    else:
        msg = _('Could not backup the following virtual machines: {failed}\n'
                ).format(backups_failed)
        msg += _(
            'Backed up {executed} out of {total} virtual machines').format(
                executed=backups_executed, total=total_backups)
    OpenStackBackupLog.objects.create()
    return msg