Beispiel #1
0
def get_ptr_from_ip(ip, region_name, request_session=None) -> dict:
    params = {'ip': ip, 'region_name': region_name}
    serializer = GetPtrFromIpSerializer(data=params)
    serializer.is_valid(raise_exception=True)

    if request_session:
        designate = designate_client(api_session=IdentityAdminApi(
            request_session=request_session).session,
                                     region_name=serializer.validated_data.pop(
                                         'region_name', None))
    else:
        designate = designate_client(api_session=IdentityAdminApi().session,
                                     region_name=serializer.validated_data.pop(
                                         'region_name', None))

    related_ip = ip_address(serializer.validated_data['ip'])
    ptr_record = related_ip.reverse_pointer + '.'
    if isinstance(related_ip, IPv6Address):
        zone_name = ptr_record
    else:
        # cut the first segment (last segment from the ip)
        zone_name = ptr_record[ptr_record.index('.') + 1:]
    try:
        zones = designate.zones.list(criterion={'name': zone_name})
    except (designate_exceptions.Base, ClientException) as e:
        raise e

    if zones:
        zone_id = zones[0]['id']
        try:
            recordsets = designate.recordsets.list(zone=zone_id,
                                                   criterion={
                                                       'type': 'PTR',
                                                       'name': ptr_record
                                                   })
        except (designate_exceptions.Base, ClientException) as e:
            LOG.error('Unable to list record sets, reason {0}'.format(e))
            raise e
        if recordsets:
            # TODO(erno): returns only the first PTR entry, and the first record
            record = recordsets[0]['records'][0]
            if record.endswith('.'):
                record = record[:-1]
            return dict(
                record=record,
                zone_id=zone_id,
            )
        else:
            dict(
                record='',
                zone_id=zone_id,
            )

    return dict(
        record='',
        zone_id='',
    )
Beispiel #2
0
def run():
    os_admin_api = IdentityAdminApi()

    for client in Client.objects.all():  # type: Client
        try:
            LOG.debug('Cleaning up for client {}'.format(client))

            if not client.first_project:
                LOG.debug('Skipping client without project ...')
                continue

            openstack_settings = OpenstackSettings.for_client(client=client)
            if openstack_settings.auto_cleanup_images:
                max_create_date = utcnow() - timedelta(
                    days=openstack_settings.auto_cleanup_number_of_days)
                images_to_cleanup = Image.objects.filter(
                    disk_format__in=openstack_settings.
                    auto_cleanup_image_types,
                    created_at__lte=max_create_date,
                    project=client.first_project,
                ).all()

                for image in images_to_cleanup:
                    os_api = Images(api_session=os_admin_api.session)
                    os_image = os_api.get(image=image)
                    # TODO: implement protected image deletion
                    if not image.protected:
                        os_image.delete()
        except Exception as e:
            LOG.exception('Error processing client {} - {}'.format(client, e))
Beispiel #3
0
def sync_hypervisors(self):
    del self  # unused
    now = utcnow()
    timestamp = now.isoformat()
    deletion_timestamp = (now - timedelta(hours=1)).isoformat()
    hh = HypervisorSyncHandler()
    version_to_delete = hh.get_version(deletion_timestamp)
    all_regions = sync_regions(auth_cache=AUTH_CACHE)
    try:
        for region in all_regions:
            for hypervisor in Hypervisors(
                    api_session=IdentityAdminApi().session).get_hypervisors(
                        region=region.id):
                hh.create_or_update(data=hypervisor,
                                    region=region.id,
                                    timestamp=timestamp)
            # delete hypervisors that were not synced in a version represented by a time less than one hour ago
            delete_filter = {
                '{}__lt'.format(hh.version_field): version_to_delete,
                'region': region.id
            }
            Hypervisor.objects.filter(**delete_filter).delete()
    except Exception as e:
        LOG.error(str(e))
        return
Beispiel #4
0
    def __init__(self, api_session=None):
        self.api_session = api_session or IdentityAdminApi().session
        self.event_handlers = {
            'volume.update.start': self.create_or_update,
            'volume.create.start': self.create_or_update,
            'volume.delete.start': self.create_or_update,
            'volume.attach.start': self.create_or_update,
            'volume.detach.start': self.create_or_update,
            'volume.resize.start': self.create_or_update,
            'volume.update.end': self.update_end,
            'volume.create.end': self.create_end,
            'volume.delete.end': self.delete,
            'volume.attach.end': self.create_or_update_attachment,
            'volume.detach.end': self.delete_attachment,
            'volume.resize.end': self.create_or_update,
            'volume.revert.start': self.create_or_update,
            'volume.revert.end': self.update_end,
            'volume.retype': self.create_or_update,
            'volume.exists': self.create_or_update,
            'compute.instance.volume.attach': self.volume_attach
        }

        self.error_handlers = {
            'scheduler.create_volume': self.create_or_update
        }
Beispiel #5
0
def upload_empty_qcow2_image(self,
                             image_id,
                             region_name,
                             disk_size_in_bytes=0):
    """
    Upload an image data to Glance as admin.
    Do not use this task in user views.
    """
    del self  # unused

    # ensure we have an empty qcow2 file to upload
    if not path.isdir(settings.FLEIO_TEMP_DIR):
        os.mkdir(settings.FLEIO_TEMP_DIR)
    qcow2_file_path = path.join(settings.FLEIO_TEMP_DIR,
                                'boot_from_iso_img.qcow2')
    if not path.isfile(qcow2_file_path):
        subprocess.call([
            'qemu-img', 'create', '-f', 'qcow2', qcow2_file_path,
            str(disk_size_in_bytes)
        ])

    if not path.isfile(qcow2_file_path):
        raise IOError('Failed to initialize temporary qcow2 file')

    admin_api = IdentityAdminApi()
    gc = glance_client(api_session=admin_api.session, region_name=region_name)
    with open(qcow2_file_path, mode="rb") as temp_file:
        gc.images.upload(image_id=image_id, image_data=temp_file)
Beispiel #6
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 #7
0
 def __init__(self, api_session=None):
     self.api_session = api_session or IdentityAdminApi().session
     self.event_handlers = {
         'qos_specs.create': self.create_or_update,
         'qos_specs.update': self.create_or_update,
         'qos_specs.delete': self.delete,
         'qos_specs.delete_keys': self.create_or_update
     }
     self.error_handlers = {'qos_specs.create': self.create_error}
Beispiel #8
0
def upload_zero_filled_image(self, image_id, region_name, length_in_bytes=0):
    """
    Upload an image data to Glance as admin.
    Do not use this task in user views.
    """
    del self  # unused

    admin_api = IdentityAdminApi()
    gc = glance_client(api_session=admin_api.session, region_name=region_name)
    buffer = BytesIO(bytearray(length_in_bytes))
    gc.images.upload(image_id=image_id, image_data=buffer)
Beispiel #9
0
 def __init__(self, api_session=None):
     self.api_session = api_session or IdentityAdminApi().session
     self.event_handlers = {
         'backup.delete.start': self.create_or_update_on_deletion_start,
         'backup.create.start': self.create_or_update,
         'backup.createprogress': self.create_or_update,
         'backup.restore.start': self.create_or_update,
         'backup.restore.end': self.create_or_update,
         'backup.exists': self.create_or_update,
         'backup.delete.end': self.delete,
         'backup.create.end': self.create_or_update_end,
     }
Beispiel #10
0
 def __init__(self, api_session=None):
     self.api_session = api_session or IdentityAdminApi().session
     self.event_handlers = {
         'magnum.cluster.create': self.create_or_update,
         'magnum.cluster.delete': self.create_or_update,
         'magnum.cluster.update': self.create_or_update,
     }
     self.error_handlers = {
         'magnum.cluster.create': self.create_or_update,
         'magnum.cluster.delete': self.create_or_update,
         'magnum.cluster.update': self.create_or_update,
     }
Beispiel #11
0
 def collect(self, project_id, region_name):
     api_session = IdentityAdminApi().session
     for collector in self.collector_instances:
         end_date = utcnow().replace(microsecond=0)
         last_collected = end_date - datetime.timedelta(days=31)
         try:
             collector.collect_events(start_date=last_collected,
                                      end_date=end_date,
                                      api_session=api_session,
                                      region_name=region_name,
                                      project_id=project_id)
         except CollectorException as e:
             LOG.error(e)
             continue
Beispiel #12
0
 def get_network_rbac(network_id, region):
     """
     Network creation and deletion does not trigger rbac events even
     if rbac rules are created if the network is shared or external, in Mitaka.
     We sync directly from the API just in case.
     """
     rbac_policies = dict(rbac_policies=list())
     try:
         admin_session = IdentityAdminApi().session
         nc = neutron_client(api_session=admin_session, region_name=region)
         rbac_policies = nc.list_rbac_policies(retrieve_all=True,
                                               object_id=network_id)
     except Exception as e:
         LOG.exception(e)
     return rbac_policies
Beispiel #13
0
 def delete_resources(project_id):
     admin_session = IdentityAdminApi().session
     gnocchi_cl = gnocchi_client(api_session=admin_session)
     try:
         resources = gnocchi_cl.resource.search(
             query={'=': {
                 'project_id': project_id
             }})
         for resource in resources:
             try:
                 gnocchi_cl.resource.delete(resource['id'])
             except NotFound:
                 pass
     except Exception as e:
         LOG.error(e)
Beispiel #14
0
    def create_router_interface(self, data, region, timestamp):
        try:
            port_id = data['router_interface']['port_id']
        except KeyError:
            return

        admin_session = IdentityAdminApi().session
        nc = neutron_client(api_session=admin_session, region_name=region)
        try:
            port = nc.show_port(port=port_id)['port']
            PortSyncHandler().create_or_update(data=port,
                                               region=None,
                                               timestamp=timestamp)
        except NotFound:
            pass
Beispiel #15
0
 def __init__(self, api_session=None):
     self.api_session = api_session or IdentityAdminApi().session
     # TODO: these need to be checked and updated
     self.event_handlers = {
         'snapshot.delete.start': self.create_or_update,
         'snapshot.create.start': self.create_or_update,
         'snapshot.createprogress': self.create_or_update,
         'snapshot.exists': self.create_or_update,
         'snapshot.update.start': self.create_or_update,
         'snapshot.update.end': self.create_or_update,
         'snapshot.revert.start': self.create_or_update,
         'snapshot.revert.end': self.create_or_update,
         'snapshot.delete.end': self.delete,
         'snapshot.create.end': self.create_or_update,
         'snapshots.reset_status.start': self.reset_status,
         'snapshots.reset_status.end': self.reset_status,
     }
Beispiel #16
0
def delete_openstack_apiusers(self, project_id):
    del self  # unused

    os_api = IdentityAdminApi()
    os_user_api = OpenStackUserApi(keystone_client=os_api.client)

    role_assignments = os_user_api.list_role_assignments(project=project_id,
                                                         include_names=True)

    # NOTE(Marius): If a user has more than one role on a project then they will have two entries for that user.
    users = [
        role_assignment.user for role_assignment in role_assignments
        if role_assignment.user['name'] != plugin_settings.username
    ]

    unique_users = {user['id']: user for user in users}
    for user_id in unique_users.keys():
        os_user_api.delete_user(user_id)
Beispiel #17
0
def import_image_from_url(self, image_id, url, region_name):
    """
    Upload an image data to Glance as admin, by downloading it first from a URL.
    Do not use this task in user views.
    """
    del self  # unused

    admin_api = IdentityAdminApi()
    gc = glance_client(api_session=admin_api.session, region_name=region_name)
    with requests.get(url, stream=True) as response:
        response.raise_for_status()
        temp_image_dir = getattr(settings, 'OPENSTACK_IMAGE_TEMP_DIR', None)
        with tempfile.TemporaryFile(dir=temp_image_dir,
                                    prefix='glance_') as temp_image_file:
            for chunk in response.iter_content(chunk_size=4096):
                if chunk:
                    temp_image_file.write(chunk)
            temp_image_file.seek(
                0)  # Go to the beginning to be able to read it
            gc.images.upload(image_id=image_id, image_data=temp_image_file)
Beispiel #18
0
def import_image_from_file(self, image_id, region_name, file_path):
    """
    Upload an image data to Glance as admin.
    Do not use this task in user views.
    """
    del self  # unused

    LOG.info('Uploading image {} in region {} from file {}'.format(
        image_id,
        region_name,
        file_path,
    ))

    admin_api = IdentityAdminApi()
    gc = glance_client(api_session=admin_api.session, region_name=region_name)
    with open(file_path, mode="rb") as temp_file:
        try:
            gc.images.upload(image_id=image_id, image_data=temp_file)
        finally:
            filename = str(temp_file.name)
            os.remove(filename)
Beispiel #19
0
    def __init__(self):
        self.event_handlers = {
            'compute.instance.create.end': self.create_or_update,
            'compute.instance.update': self.create_or_update,
            'compute.instance.power_off.end': self.create_or_update,
            'compute.instance.power_on.end': self.create_or_update,
            'compute.instance.resize.end': self.create_or_update,
            'compute.instance.resize.revert.end': self.create_or_update,
            'compute.instance.finish_resize.end': self.create_or_update,
            'compute.instance.resize.confirm.end': self.create_or_update,
            'compute.instance.rescue.end': self.create_or_update,
            'compute.instance.unrescue.end': self.create_or_update,
            'compute.instance.rebuild.end': self.create_or_update,
            'compute.instance.migrate.end': self.create_or_update,
            'compute.instance.shutdown.end': self.create_or_update,
            'compute.instance.delete.end': self.delete,
            'compute.instance.create.start': self.create_or_update,
            'compute.instance.delete.start': self.create_or_update
        }

        self.error_handlers = {}
        self.admin_api_session = IdentityAdminApi().session
Beispiel #20
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 #21
0
    def to_internal_value(self, data):
        """
        Perform any data modification here.
        to_internal_value is called before .validate() and after each field is validated.
        """
        request = self.context.get('request', None)
        assert request, 'Serializer can only be used with http requests'

        value = super(AdminInstanceCreateSerializer,
                      self).to_internal_value(data)

        errors = OrderedDict()
        db_region = value['region']

        client = value['client']
        flavor = value['flavor']
        boot_source = value['boot_source']
        share_image = value['share_image']

        # Try to get a project by client
        project = client.first_project
        if project is None:
            raise ValidationError({
                'detail':
                _('Unable to find a client with an OpenStack project associated'
                  )
            })
        value['project'] = project

        # Validate boot source
        if boot_source['source_type'] in ('image', 'owned_image',
                                          'shared_image', 'requested_image',
                                          'community_image'):
            try:
                openstack_models.Image.objects.get_images_for_project(
                    project_id=project.project_id).get(
                        id=boot_source['source_id'])
            except openstack_models.Image.DoesNotExist:
                # Share the image with the client's project if it exists
                if share_image:
                    try:
                        db_image = openstack_models.Image.objects.get(
                            id=boot_source['source_id'])
                    except openstack_models.Image.DoesNotExist:
                        raise ValidationError(
                            {'boot_source': _('Image not found')})
                    else:
                        try:
                            request_session = getattr(
                                self.context.get('request'), 'session', None)
                            admapi = IdentityAdminApi(
                                request_session=request_session)
                            if db_image.visibility == OpenStackImageVisibility.PRIVATE:
                                api_image = Image(db_image=db_image,
                                                  api_session=admapi.session)
                                api_image.set_visibility(
                                    visibility=OpenStackImageVisibility.SHARED)
                                api_image.create_member(
                                    member_project_id=client.first_project.
                                    project_id)
                            elif db_image.visibility == OpenStackImageVisibility.SHARED:
                                api_image = Image(db_image=db_image,
                                                  api_session=admapi.session)
                                api_image.create_member(
                                    member_project_id=client.first_project.
                                    project_id)
                        except Exception as e:
                            LOG.exception(e)
                            raise ValidationError({
                                'boot_source':
                                _('Unable to boot: {}').format(e)
                            })
                else:
                    raise ValidationError(
                        {'boot_source': _('Image not found')})
        else:
            try:
                if boot_source['source_type'] in ('volume',
                                                  'requested_volume'):
                    openstack_models.Volume.objects.get(
                        id=boot_source['source_id'],
                        project__project_id=project.project_id)
                elif boot_source['source_type'] == 'volume_snapshot':
                    openstack_models.VolumeSnapshot.objects.get(
                        id=boot_source['source_id'],
                        project__project_id=project.project_id)
                else:
                    openstack_models.Volume.objects.get(
                        id=boot_source['source_id'],
                        project__project_id=project.project_id)
            except openstack_models.Volume.DoesNotExist:
                raise ValidationError(
                    {'boot_source': _('Volume not available')})
            except openstack_models.VolumeSnapshot.DoesNotExist:
                raise ValidationError(
                    {'boot_source': _('Volume snapshot not available')})

        # Nics
        compute_api_version = APIVersion(plugin_settings.COMPUTE_API_VERSION)
        nics = value.get('nics')
        if nics:
            value['nics'] = [{'net-id': n} for n in nics]
        elif compute_api_version > APIVersion('2.37'):
            if plugin_settings.AUTO_ALLOCATED_TOPOLOGY:
                value['nics'] = 'auto'
            else:
                value[
                    'nics'] = 'none'  # neutron expects it as none string rather than bool

        # SSH Keys
        ssh_keys = value.get('ssh_keys', None)
        if ssh_keys:
            ssh_keys = json.loads(ssh_keys)
            pkm_keys_dict = {}
            for ssh_key in ssh_keys:
                try:
                    pkm_key = PublicKey.objects.get(
                        id=ssh_key, user__in=client.users.all())
                    pkm_keys_dict[ssh_key] = newlines_substract(
                        pkm_key.public_key)
                except PublicKey.DoesNotExist:
                    errors['ssh_keys'] = [_('SSH Key not found')]
            value['ssh_keys'] = pkm_keys_dict

        # Set the actual flavor. Note that flavor names are unique per region.
        if flavor.region != db_region:
            errors['flavor'] = [_('Flavor not in {}'.format(db_region.id))]

        if errors:
            raise ValidationError(errors)

        return value
Beispiel #22
0
 def identity_admin_api(self):
     if hasattr(self, 'request'):
         return IdentityAdminApi(request_session=self.request.session)
     else:
         return IdentityAdminApi()
Beispiel #23
0
    def create_project(self, client, openstack_product=None, openstack_product_cycle=None, **kwargs):
        """
        Create the project with the OpenStack Keystone API, add `admin` (plugin_settings.USERNAME)
        user rights (plugin_settings.DEFAULT_ROLE) to it and return the corresponding Fleio database object.
        """
        extra_fields = kwargs.copy()
        admin_api = IdentityAdminApi()

        service_external_id = extra_fields.pop('service_external_id', None)
        if 'project_id' not in extra_fields:
            project_context = {'client': client}
            try:
                project_name = Template(settings.plugin_settings.default_project_name).render(Context(project_context))
                desc_tpl = settings.plugin_settings.default_project_description
                project_description = Template(desc_tpl).render(Context(project_context))
            except Exception as e:
                LOG.exception(e)
                project_name = '{} - {}'.format(client.name, client.id)
                project_description = 'Fleio created for {}'.format(client.name)

            project = admin_api.create_project(project_name,
                                               settings.plugin_settings.PROJECT_DOMAIN_ID,
                                               project_description)
            admin_api.grant_user_role(project.id,
                                      settings.plugin_settings.USERNAME,
                                      settings.plugin_settings.DEFAULT_ROLE)

            extra_fields['project_id'] = project.id
            extra_fields['name'] = project_name
            extra_fields['description'] = project_description
        else:
            admin_api.grant_user_role(extra_fields['project_id'],
                                      settings.plugin_settings.USERNAME,
                                      settings.plugin_settings.DEFAULT_ROLE)

        if openstack_product is None:
            # no openstack product provided, get product from client configuration
            client_configuration = client.billing_settings

            try:
                openstack_product = Product.objects.get(id=client_configuration.auto_order_service)
            except Product.DoesNotExist:
                openstack_product = Product.objects.filter(product_type='openstack').first()
            if openstack_product:
                cycle_id = client_configuration.auto_order_service_cycle
                openstack_product_cycle = openstack_product.cycles.filter(id=cycle_id).first()
            else:
                openstack_product_cycle = None

        try:
            with transaction.atomic():
                # create service
                service = self.create_service(client, openstack_product, openstack_product_cycle, service_external_id)

                # create project
                db_project = self.create(service=service, **extra_fields)
        except IntegrityError:
            # TODO: we are getting integrity errors because updated manages to create project first
            # attempt to update existing project
            db_project = self.filter(project_id=extra_fields['project_id']).first()
            if db_project is not None:
                with transaction.atomic():
                    # create service for project
                    service = self.create_service(
                        client,
                        openstack_product,
                        openstack_product_cycle,
                        service_external_id
                    )

                    db_project.service = service
                    db_project.save(update_fields=['service'])
            else:
                LOG.error('Failed to create or update project')

        return db_project
Beispiel #24
0
 def gnocchi_admin(self):
     if self.gca is None:
         self.gca = gnocchi_client(api_session=IdentityAdminApi().session,
                                   region_name=self.region_name)
     return self.gca
Beispiel #25
0
def create_instance_from_iso_task(volume_id,
                                  project_id,
                                  project_domain_id,
                                  region_name,
                                  name,
                                  image,
                                  flavor,
                                  nics,
                                  block_device_mapping_v2,
                                  block_device_mapping,
                                  user_data,
                                  admin_pass=None,
                                  key_name=None,
                                  key_content=None,
                                  **create_args):
    boot_image_id = image
    identity_admin_api = IdentityAdminApi()

    # wait for image
    if not wait_for(
            lambda: Image.objects.filter(id=boot_image_id).first().status ==
            OpenStackImageStatus.ACTIVE, 600):
        raise InstanceTaskException(_('Upload image failed '))
    region = OpenstackRegion.objects.get(id=region_name)
    boot_image_model = Image.objects.get(id=boot_image_id)
    unique_name = '{}'.format(uuid4())
    os_image_api = Images(api_session=identity_admin_api.session)

    # copy properties starting with hw_ to new image
    extra_properties = {}
    prefixes = getattr(settings, 'OPENSTACK_CREATE_FROM_ISO_PROPERTY_PREFIXES',
                       [])
    for property_name in boot_image_model.properties:  # type: str
        for prefix in prefixes:
            if property_name.startswith(prefix):
                extra_properties[property_name] = boot_image_model.properties[
                    property_name]

    owner = project_id if project_id else identity_admin_api.project_id
    disk_format = getattr(settings, 'OPENSTACK_CREATE_FROM_ISO_IMAGE_TYPE',
                          'raw')

    try:
        new_image = os_image_api.create(
            owner=owner,
            name=unique_name,
            min_disk=1,
            min_ram=1,
            container_format='bare',
            disk_format=disk_format,
            visibility='community',
            protected=False,
            architecture=boot_image_model.architecture,
            os_distro=boot_image_model.os_distro,
            os_version=boot_image_model.os_version,
            region=region,
            hypervisor_type=boot_image_model.hypervisor_type,
            file=None,
            url=None,
            source=None,
            properties=extra_properties,
        )
    except Exception as e:
        del e  # unused
        LOG.exception(
            'Create instance failed. (owner: {}, disk_format: {}, extra_properties: {}'
            .format(owner, disk_format, extra_properties))
        return None
    else:
        try:
            if disk_format == 'qcow2':
                upload_empty_qcow2_image(new_image.id,
                                         region_name=region_name,
                                         disk_size_in_bytes=1)
            else:
                upload_zero_filled_image(new_image.id,
                                         region_name=region_name,
                                         length_in_bytes=1)
        except Exception as e:
            LOG.exception(
                'Failed to create temporary image when booting from iso: {}'.
                format(e))
            try:
                db_image = Image.objects.get(id=new_image.id)
                os_image_api.get(image=db_image).delete()
            except Exception as e:
                LOG.exception('Failed to delete image: {}'.format(e))
            return None

        instance_id = create_instance_task(
            volume_id=volume_id,
            project_id=project_id,
            project_domain_id=project_domain_id,
            region_name=region_name,
            name=name,
            image=new_image.id,
            flavor=flavor,
            admin_pass=admin_pass,
            nics=nics,
            key_name=key_name,
            key_content=key_content,
            block_device_mapping_v2=block_device_mapping_v2,
            user_data=user_data,
            block_device_mapping=block_device_mapping,
            **create_args,
        )

        activity_helper.add_current_activity_params(object_id=instance_id)

        if not wait_for(
                lambda: ModelInstance.objects.filter(id=instance_id).first(),
                max_time=300):
            raise InstanceTaskException(_('Failed to create instance'))
        if not wait_for(lambda: ModelInstance.objects.filter(id=instance_id).
                        first().status == 'active',
                        max_time=300):
            raise InstanceTaskException(_('Failed to create instance'))
        if not wait_for(lambda: not ModelInstance.objects.filter(
                id=instance_id).first().task_state,
                        max_time=300):
            raise InstanceTaskException(_('Failed to create instance'))

        try:
            db_image = Image.objects.get(id=new_image.id)
            os_image_api.get(image=db_image).delete()
        except Exception as e:
            LOG.exception('Failed to delete image: {}'.format(e))

        instance_model = ModelInstance.objects.get(id=instance_id)
        instance_model.booted_from_iso = True
        instance_model.save()
        instance_api = Instance.with_admin_session(instance=instance_model)
        instance_api.rescue(image=boot_image_id)

        signal_boot_from_iso.delay(instance_id=instance_id,
                                   is_new_instance=True)

        return instance_id
Beispiel #26
0
def move_instance_task(self, instance_id: str, destination_project_id: str):
    del self  # unused

    # intentionally let this throw an error to fail task if UUID not found in DB
    db_instance = ModelInstance.objects.get(id=instance_id)
    api_instance = Instance.with_admin_session(instance=db_instance)
    destination_project = OpenstackProject.objects.get(
        project_id=destination_project_id)

    identity_admin_api = IdentityAdminApi()

    unique_name = '{}.{}.{}'.format('move', api_instance.instance.id, uuid4())
    if api_instance.instance.status == 'active':
        api_instance.stop()
        if not wait_for(
                lambda: ModelInstance.objects.get(id=api_instance.instance.id).
                status == 'stopped',
                max_time=300,
        ):
            raise InstanceTaskException(
                _('Move instance: failed to stop source instance'))
        api_instance.instance.refresh_from_db()

    api_instance.create_snapshot(unique_name)
    if not wait_for(
            lambda: ModelImage.objects.filter(name=unique_name).count() > 0,
            max_time=300,
    ):
        raise InstanceTaskException(
            _('Move instance: failed to create source instance snapshot'))
    if not wait_for(
            lambda: ModelImage.objects.filter(name=unique_name).first().status
            == OpenStackImageStatus.ACTIVE,
            max_time=300,
    ):
        raise InstanceTaskException(
            _('Move instance: failed to create source instance snapshot'))

    db_image = ModelImage.objects.get(name=unique_name)
    os_image = APIImages(api_session=identity_admin_api.session).get(
        image=db_image)  # type: APIImage
    os_image.set_visibility(visibility=OpenStackImageVisibility.SHARED)
    os_image.create_member(member_project_id=destination_project.project_id)

    nics = []
    for port in OpenstackPort.objects.filter(
            device_id=api_instance.instance.id).all():
        if port.network:
            nic = {
                'net-id': port.network.id,
            }
            if len(port.fixed_ips) > 0:
                api_port = APIPorts(
                    api_session=identity_admin_api.session).get(
                        port=port)  # type: APIPort
                args = {
                    'region': api_instance.instance.region,
                    'fixed_ips': [port.fixed_ips[0]]
                }
                api_port.remove_ip(kwargs=args)
                nic['v4-fixed-ip'] = port.fixed_ips[0]['ip_address']
                del port.fixed_ips[0]
                port.save()
            nics.append(nic)

    new_instance_id = create_instance_task(
        volume_id=None,
        project_id=destination_project.project_id,
        project_domain_id=destination_project.project_domain_id,
        region_name=api_instance.instance.region,
        name=api_instance.instance.name,
        image=db_image.id,
        flavor=api_instance.instance.flavor_id,
        admin_pass=None,
        nics=nics,
        key_name=None,
        key_content=None,
        block_device_mapping_v2=None,
        block_device_mapping=None)

    if not wait_for(lambda: ModelInstance.objects.filter(id=new_instance_id).
                    count() > 0,
                    max_time=600):
        raise InstanceTaskException(
            _('Move instance: failed to create instance from snapshot'))

    if not wait_for(lambda: ModelInstance.objects.filter(id=new_instance_id).
                    first().status == 'active',
                    max_time=600):
        raise InstanceTaskException(
            _('Move instance: failed to create instance from snapshot'))

    if not wait_for(lambda: not ModelInstance.objects.filter(
            id=new_instance_id).first().task_state,
                    max_time=600):
        raise InstanceTaskException(
            _('Move instance: failed to create instance from snapshot'))

    os_image.delete()

    for port in OpenstackPort.objects.filter(
            device_id=api_instance.instance.id).all():
        if port.network:
            new_instance_port = OpenstackPort.objects.filter(
                device_id=new_instance_id,
                network__id=port.network.id).first()
            if new_instance_port:
                api_port = APIPorts(
                    api_session=identity_admin_api.session).get(
                        port=port)  # type: APIPort
                new_instance_api_port = APIPorts(
                    api_session=identity_admin_api.session).get(
                        port=new_instance_port)  # type: APIPort
                for index in range(len(port.fixed_ips)):
                    args = {
                        'region': api_instance.instance.region,
                        'fixed_ips': [port.fixed_ips[index]]
                    }
                    api_port.remove_ip(kwargs=args)
                    new_instance_api_port.add_ip(kwargs=args)

    api_instance.rename('{} ({})'.format(api_instance.instance.name,
                                         _('MOVED')))

    return True
Beispiel #27
0
 def openstack_admin_session(self):
     if self.request and self.request.session:
         return IdentityAdminApi(
             request_session=self.request.session).session
     else:
         return IdentityAdminApi().session
Beispiel #28
0
    def create_openstack_service(self, request, pk):
        del pk  # unused

        # TODO - #1019: implement proper creation of service here
        serializer = CreateServiceSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        client = self.get_object()

        if client.first_project is not None and client.first_project.deleted is False:
            raise ForbiddenException(
                {'detail': _('Client already has a project')})

        project_id = serializer.validated_data.get('project_id', 'none')

        if Client.objects.filter(
                services__openstack_project__project_id=project_id):
            raise ForbiddenException(
                {'detail': _('Project already associated with a client')})

        openstack_product = Product.objects.get(
            id=serializer.validated_data['product_id'])
        openstack_product_cycle = openstack_product.cycles.filter(
            id=serializer.validated_data['product_cycle_id'])[0]
        service_external_id = serializer.validated_data.get(
            'service_external_id', None)

        with transaction.atomic():
            if serializer.validated_data['create_new_project']:
                try:
                    ProjectModel.objects.create_project(
                        client=client,
                        openstack_product=openstack_product,
                        openstack_product_cycle=openstack_product_cycle,
                        service_external_id=service_external_id,
                    )
                except Conflict:
                    return Response(
                        status=409,
                        data={
                            'detail':
                            _('A project already exists for this client')
                        })
                except RoleDoesNotExist:
                    # TODO: going to the exact settings page and field isn't implemented yet in frontend
                    # on implementation in frontend change section and configuration_id if necessary
                    # (Issue: https://git.fleio.org/fleio/fleio/issues/1922)
                    if plugin_settings.default_role:
                        error_message = _(
                            'Role "{}" does not exist in OpenStack. Set an existing role as default '
                            'role.').format(plugin_settings.default_role)
                    else:
                        error_message = _(
                            'OpenStack role was not set in OpenStack settings -> defaults tab. '
                            'Set an existing role as default role.')
                    raise ConfigException(message=error_message,
                                          section='openstack_plugin_defaults',
                                          configuration_id='default_role')
            else:
                try:
                    project = IdentityAdminApi(
                        request_session=request.session).client.projects.get(
                            project_id)
                except NotFound:
                    raise ObjectNotFound({'detail': _('Project not found')})
                except ConnectFailure:
                    raise ServiceUnavailable(
                        {'detail': _('Could not connect to openstack')})

                with transaction.atomic():
                    try:
                        ProjectModel.objects.create_project(
                            client=client,
                            openstack_product=openstack_product,
                            openstack_product_cycle=openstack_product_cycle,
                            service_external_id=service_external_id,
                            project_id=project.id,
                            project_domain_id=project.domain_id,
                            disabled=not project.enabled,
                            extras={
                                'name': project.name,
                                'description': project.description,
                                'is_domain': project.is_domain
                            }).save()
                    except RoleDoesNotExist:
                        # TODO: going to the exact settings page and field isn't implemented yet in frontend
                        # on implementation in frontend change section and configuration_id if necessary
                        # (Issue: https://git.fleio.org/fleio/fleio/issues/1922)
                        if plugin_settings.default_role:
                            error_message = _(
                                'Role "{}" does not exist in OpenStack. Set an existing role as default '
                                'role.').format(plugin_settings.default_role)
                        else:
                            error_message = _(
                                'OpenStack role was not set in OpenStack settings -> defaults tab. '
                                'Set an existing role as default role.')
                        raise ConfigException(
                            message=error_message,
                            section='openstack_plugin_defaults',
                            configuration_id='default_role')

        return Response({'detail': _('Ok')})
Beispiel #29
0
LOG = logging.getLogger(__name__)

from django.conf import settings  # noqa

from fleio.billing.settings import CyclePeriods  # noqa
from fleio.openstack.models.network_port_traffic import NetworkPortTrafficTypes  # noqa
from fleio.openstack.api.identity import IdentityAdminApi  # noqa
from fleio.openstack.metrics import GnocchiMetrics  # noqa
from fleio.openstack.models import Instance, Project  # noqa
from fleio.openstack.models import OpenstackRegion, NetworkPortResource  # noqa
from fleio.openstack.models import Port as PortModel  # noqa
from fleio.openstack.models import NetworkPortTraffic  # noqa


os_admin_api = IdentityAdminApi()

IGNORE_UNRESOLVED_RESOURCE = True

INCOMING_BYTES_METRIC = 'network.incoming.bytes'
OUTGOING_BYTES_METRIC = 'network.outgoing.bytes'

RESOURCE_LIST_PAGE_SIZE = 100
RESOURCE_TYPE = 'instance_network_interface'

BYTES_PER_GB = 1024 * 1024 * 1024

TRAFFIC_DATA_GRANULARITY = getattr(settings, 'TRAFIC_DATA_GRANULARITY', 300)
PUBLIC_TRAFFIC_ONLY = getattr(settings, 'INSTANCE_TRAFFIC_DISPLAY', 'all') == 'public'

Beispiel #30
0
 def get_session():
     return IdentityAdminApi().session