Homelab, Linux & ABAP (~˘▾˘)~

[ABAP] Clean Code

ABAP Clean Code

DRY – Don’t repeat yourself

KISS – Keep it simple, stupid

YAGNI – You ain’t gonna need it

PEBKAC – Problem Exist Between Keyboard And Chair

SoC – Separation of concerns

Issues generally come in three forms:

  1. syntax errors that prevent a program from running
  2. runtime errors when code fails to execute or has unexpected behavior
  3. semantic (or logical) errors when code doesn’t do what it’s meant to

[Mint] Citrix Receiver on multiple monitors

Citrix Receiver download.
Here is the offical how to guide.

The following command can be used to test for window manager support.
If there is no output, there is no support.

xprop -root | grep _NET_WM_FULLSCREEN_MONITORS

Further troubleshooting infos here.

In my case, I just had to launch the configuration manager and set it to “Full Screen”.


If needed, the resolutions settings can be found here:



[ABAP] Read Infotype

DATA: ls_p0001           TYPE p0001,
      lt_p0001           TYPE TABLE OF p0001,  
      lr_infotype_reader TYPE REF TO if_hrpa_read_infotype, 
      lt_infotype        TYPE hrpad_prelp_tab, 
      ls_infotype        TYPE prelp, 
      lv_missing_auth    TYPE boole_d 
      lv_data_exists     TYPE boole_d. 

* Infotyp reader initialisieren
   CALL METHOD cl_hrpa_read_infotype=>get_instance
       infotype_reader = lr_infotype_reader.

 * Infotyp 1 lesen
   CLEAR lt_infotype.
   CALL METHOD lr_infotype_reader->read
       tclas         = 'A'
       pernr         = lv_pernr
       infty         =  '0001' 
       begda         = iv_begda
       endda         = iv_endda
       no_auth_check = abap_true
       infotype_tab  = lt_infotype
       data_exists   = lv_data_exists
       missing_auth  = lv_missing_auth.

   LOOP AT lt_infotype INTO ls_infotype.
     CALL METHOD cl_hr_pnnnn_type_cast=>prelp_to_pnnnn
         prelp = ls_infotype
         pnnnn = ls_p0001.
        APPEND ls_p0001 TO lt_p0001.

[Proxmox] Mount dataset into LXC

Open LXC config file in your favorite editor. In this case the container name is 101:

nano /etc/pve/lxc/101.conf

Append a single line for each mountpoint you want to add. The first mountpoint is “mp0”, the second “mp1” and so on.

mp0: /data/music,mp=/mnt/nfs/music

First the source (my zpool “data”, folowing the dataset name “music”), after that the destination inside the container beginning “mp=”.

[ABAP] Idoc MBGMCR – Goods Movement

  METHOD create_mbgmcr_idoc.

    set_idoc_control(         IMPORTING es_idoc_control  = DATA(ls_idoc_control) ).

    map_mbgmcr_data(          EXPORTING is_data          = is_data
                              IMPORTING es_kopf          = DATA(ls_kopf)
                                        es_head          = DATA(ls_head)
                                        es_code          = DATA(ls_code)
                                        et_item          = DATA(lt_item) ).

    set_idoc_data(            EXPORTING is_kopf          = ls_kopf
                                        is_head          = ls_head
                                        is_code          = ls_code
                                        it_item          = lt_item
                              IMPORTING et_idoc_data     = DATA(lt_idoc_data) ).

    idoc_inbound_write_to_db( IMPORTING ev_idoc_number   = DATA(lv_docnum)
                              CHANGING  ct_idoc_data     = lt_idoc_data
                                        cs_idoc_control  = ls_idoc_control  ).

    idoc_start_inbound(       EXPORTING it_idoc_data     = lt_idoc_data
                                        is_idoc_control  = ls_idoc_control ).

    get_idoc_status(          EXPORTING iv_docnum        = lv_docnum ).


Method set_idoc_control:

  METHOD set_idoc_control.

    CLEAR es_idoc_control.

    " Lese Partnummer
    SELECT SINGLE logsys FROM t000 INTO @DATA(lv_logsys)
            WHERE mandt = @sy-mandt.

    " IDOC Basisdaten
    es_idoc_control-mandt     = sy-mandt.
    es_idoc_control-direct    = '2'.                "Richtung der IDoc-Übertragung: Eingang
    es_idoc_control-idoctp    = mc_idoctp.          "MBGMCR03
    es_idoc_control-mestyp    = mc_mestyp.          "MBGMCR
    es_idoc_control-mescod    = mc_mescod.          "Logische Nachrichtenvariante
    " Empfänger
    es_idoc_control-rcvpor    = |SAP{ sy-sysid }|.  "Empfängerport (SAP-System, EDI-Subsystem)
    es_idoc_control-rcvprt    = mc_rcvprt.          "Partnerart des Empfängers (LS)
    es_idoc_control-rcvprn    = lv_logsys.          "Partnernummer des Empfängers
    " Sender
    es_idoc_control-sndpor    = |SAP{ sy-sysid }|.  "Absenderport (SAP-System, EDI-Subsystem)
    es_idoc_control-sndprt    = mc_rcvprt.          "Partnerart des Absenders (LS)
    es_idoc_control-sndprn    = lv_logsys.          "Partnernummer des Absenders


Method map_mbgmcr_data:

  METHOD map_mbgmcr_data.

    "Hinweis: Zum Füllen der Strukturen, siehe auch Dokumentation für BAPI_GOODSMVT_CREATE.

    CLEAR: es_kopf, es_head, es_code, et_item.

    es_kopf = VALUE #( testrun    = gs_sel-test ).

    es_head = VALUE #( pstng_date = sy-datum
                       doc_date   = sy-datum ).

    es_code = VALUE #( gm_code    = mc_gm_code_04 ).                       "Code 04: Umbuchung

    et_item = VALUE #( ( is_data ...) ). 


Method set_idoc_data:

  METHOD set_idoc_data.

    CLEAR et_idoc_data.

    et_idoc_data = VALUE #( ( segnam = 'E1MBGMCR'                sdata = is_kopf segnum = 1 psgnum = 1 hlevel = 1 )
                            ( segnam = 'E1BP2017_GM_HEAD_01'     sdata = is_head segnum = 2 psgnum = 2 hlevel = 2 )
                            ( segnam = 'E1BP2017_GM_CODE'        sdata = is_code segnum = 3 psgnum = 2 hlevel = 2 ) ).

    DO lines( it_item ) TIMES.
      APPEND VALUE #( segnam = 'E1BP2017_GM_ITEM_CREATE' sdata = it_item[ sy-index ] segnum = ( 3 + sy-index ) psgnum = 2 hlevel = 2 ) TO et_idoc_data.


Method idoc_inbound_write_to_db :

  METHOD idoc_inbound_write_to_db.

    CLEAR : ev_idoc_number, ev_state, ev_inb_process_data.

        pi_do_handle_error      = abap_true
        pi_return_data_flag     = abap_true
        pe_idoc_number          = ev_idoc_number
        pe_state_of_processing  = ev_state
        pe_inbound_process_data = ev_inb_process_data
        t_data_records          = ct_idoc_data
        pc_control_record       = cs_idoc_control
        idoc_not_saved          = 1
        OTHERS                  = 2.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE zcx_ecos_goods_movement
          textid = VALUE scx_t100key( msgid = sy-msgid
                                      msgno = sy-msgno
                                      attr1 = sy-msgv1
                                      attr2 = sy-msgv2
                                      attr3 = sy-msgv3
                                      attr4 = sy-msgv4 ).

    gr_listlog->append_log_entry( iv_type = gr_listlog->gc_log_type_statistic
                                  iv_text = |Idoc mit der Nummer { ev_idoc_number } angelegt.|
                                  iv_alog = abap_true ).


Method idoc_start_inbound :

  METHOD idoc_start_inbound.

    DATA: lt_idoc_control TYPE TABLE OF edidc.

    APPEND is_idoc_control TO lt_idoc_control.

        pi_do_commit                  = abap_true
        t_control_records             = lt_idoc_control
        t_data_records                = it_idoc_data
        invalid_document_number       = 1
        error_before_call_application = 2
        inbound_process_not_possible  = 3
        old_wf_start_failed           = 4
        wf_task_error                 = 5
        serious_inbound_error         = 6
        OTHERS                        = 7.
    IF sy-subrc <> 0.
          textid = VALUE scx_t100key( msgid = sy-msgid
                                      msgno = sy-msgno
                                      attr1 = sy-msgv1
                                      attr2 = sy-msgv2
                                      attr3 = sy-msgv3
                                      attr4 = sy-msgv4 ).


Method get_idoc_status:

  METHOD get_idoc_status.

    SELECT SINGLE status FROM edidc INTO @DATA(lv_status) WHERE docnum = @iv_docnum.

    gr_listlog->append_log_entry( iv_type = gr_listlog->gc_log_type_statistic
                              iv_text = |Idoc Status: { lv_status }|
                              iv_alog = abap_true ).


[ZFS] Basic Commands

Manual Pages:

modinfo zfs                               //check current ZFS version
zfs list                                  //list pool with datasets
zfs list -r pool                          //show all datasets in a pool with size and mountpoint
zfs list -r -o name,mountpoint,mounted    //check if datasets are mounted   
zpool status (pool)
zpool list
zpool list -v
zpool iostat (pool 1)
zpool iostat -v

Activate NFS on dataset:

zfs set sharenfs=on pool/dataset
zfs get sharenfs pool/dataset

Usefull comands when replacing a failed disk:

ls -l /dev/disk/by-id/                // Disk ID's
zdb                                   // Display zpool debugging and consistency information
smartctl -a /dev/ada0                 // S.M.A.R.T info
wipefs -a new_hdd                     // remove ext4 filesystem 
zpool replace data old_hdd new_hdd    // Replace HDD

Scrub cronjob:

cat /etc/cron.d/zfsutils-linux 

Add and remove Log & L2ARC:

zpool add data log sda1
zpool add data cache sda2

zpool remove data log sda1
zpool remove data cache sda2

[Pi-hole] Blocklists

How to update: pihole -up


You will find further blocklists here, here and here.
For whitelists look here.
For Regex Filter check here.

Test your Ad Blocking:

If you would like to have a Dark Theme for Pi-Hole look here or use the Firefox/Chrome extension Dark Reader.

Other interesting projects: