Le cache ARP (Address Resolution Protocol) est une table qui associe une adresse IP à une adresse mac, ces dernières sont utilisées pour les connexions
Le problème qui peut intervenir, c’est si vous changez une adresse IP sur une machine de votre SI, il est possible que cette information pollue votre connexion, n’étant pas mise à jour en temps réel.
Vous pouvez régler cette fréquence par la commande CHGTCPA.
La valeur est exprimée en minutes et le plus souvent 15 minutes est un bon compromis !
Votre cache est réinitialisée par un IPL ou par un arrêt de TCP/IP c’est un peu brutal, on va voir comment le consulter et comment agir dessus.
En utilisant navigator for i
Vous devez sélectionner Lignes dans le menu déroulant
Vous pouvez voir votre cache en cliquant sur Mémoire cache ARP
Vous pouvez supprimer une entrée en cliquant dessus ou même supprimer toutes les entrées en cliquant sur suppression globale
Vous pouvez également intervenir en 5250
Vous pouvez clearer le cache en passant la commande CHGTCPDMN (sans paramètre) https://www.ibm.com/support/pages/dns-query-returning-old-ip-address
Pour le reste il existe des API
par exemple :
QtocRmvARPTblE pour clearer QtocLstPhyIfcARPTbl pour lister les entrées du cache dans un user space
Vous pouvez donc soit coder un outil, soit en récupérer un sur internet on vous met celui qu’on utilise sur mon github.
Nous utilisons de plus en plus de certificats pour crypter nos communications. Leur gestion via DCM sur l’IBM i devient donc de plus en plus nécessaire et « subtile ».
Les outils standards
Interface web de DCM (Digital Certificate Manager)
Beaucoup plus pratique et réactive depuis sa réécriture, elle comprend l’ensemble des fonctions (presque en réalité) : création des autorités, création des certificats, gestion des applications (au sens DCM), affectation, renouvellement, importation et exportation :
C’est propre, pratique.
Pour rappel, le principe : DCM permet de gérer les certificats (stocker, renouveler etc …), mais également de les affecter à une ou plusieurs applications IBM i. La notion d’application dans DCM est proche d’une notion de service : serveur telnet, serveur http, serveur ou client FTP et bien d’autres.
Ainsi un certificat peut être assigné à aucune, une ou plusieurs applications :
Et chaque application dispose de ses propres attributs, permettant par exemple de choisir les niveaux de protocoles :
A priori, on a pas de raison d’aller modifier ces attributs très souvent, l’interface web est parfaite pour ces actions
Services SQL
Pour plus de facilité, et de capacité d’automatisation, IBM délivre une fonction table (UTDF) : qsys2.certificate_info
Grâce à Jesse Gorzinski (M. Open Source chez IBM), vous disposez également de commandes shell pour effectuer les principales actions de DCM : création, affectation de certificats, liste …
Il faut absolument l’installer, cela vous permet d’automatiser de nombreuses actions courantes.
Exemple :
Les applications ?
« Houston, nous avons un problème ! ». Pas si grave non plus …
Il est facile de déterminer quels sont les certificats expirés ou qui vont expirer. Donc ceux à renouveler (création par DM ou importation). Par contre, seul l’interface web de DCM permet de voir les applications assignées, et donc les impacts de la péremption du certificat !
La connaissance des applications est primordiale : certaines nécessitent un arrêt/redémarrage du service (donc une interruption pour les utilisateurs), d’autres non.
Si aucune application n’est liée, on ne va peut être rien faire. Sinon, on va anticiper (sisi).
DCM permet de voir les applications, mais il vous faut aller sur le certificat et voir le détail par l’interface graphique. Donc humainement sur chacune de vos partitions.
API -> fonction table (UDTF)
Cette information est accessible par les APIs de DCM.
Pour plus de faciliter, nous vous proposons une fonction table SQL : listedcmapplication
L’objectif est de lister les applications ET les certificats associés :
Les deux paramètres permettent de sélectionner les applications avec ou sans certificat, les applications serveur ou client.
Vous pouvez également facilement utiliser les informations conjointes de qsys2.certificate_info. Par exemple, quels certificats vont expirer dans le mois et quelles sont les applications impactées :
Le code est open source, il est perfectible, n’hésitez pas à participer !
Quelques idées : agrégation des informations de différentes partitions, service correspondant actif ou non …
https://www.gaia.fr/wp-content/uploads/2023/02/dcm.png268618Nathanaël Bonnet/wp-content/uploads/2017/05/logogaia.pngNathanaël Bonnet2023-02-14 08:33:362023-02-14 08:35:31Gérer vos certificats par DCM
Vous avez besoin d’afficher une fenêtre avec un titre est un texte , par exemple dans des opérations d’administration
Vous pouvez utiliser un écran de type DSPF et un programme associé voici une alternative intéressante en utilisant DSM (Dynamic Screen Manager) qui vous permettra de créer dynamiquement un écran à la volée sans source à compiler
Nous utilisons de plus en plus les services SQL pour de nombreuses actions : accès aux *DTAQ, *DTAARA, travaux etc …
Par exemple, pour accéder au contenu d’une variable d’environnement, la vue QSYS2.ENVIRONMENT_VARIABLE_INFO est très simple à utiliser :
Dans un programme RPG, il est très simple d’effectuer une lecture SQL.
Mais dans certains cas, nous préférerons utiliser les APIs système : pour la performance, ou dans le CL ! En CL, il est possible d’exécuter une instruction SQL, mais pas de récupérer un result sets (en tout cas pas simplement et avec une bonne performance).
L’appel d’API depuis le CL ne pose pas de soucis, principalement depuis les évolutions permettant de maitriser l’allocation mémoire des variables (variables autonomes, basées sur un pointeur, ou basée sur une autre variable – équivalent OVERLAY du RPG) :
Maintenant, lorsque l’on utilise des API, il est (souvent) nécessaire de passer par des pointeurs, de façon explicite ou non. Par exemple, c’est le cas pour QUSRJOBI même si l’on a pas déclaré de pointeur dans notre programme CL :
En réalité, lors d’un appel de programme ou procédure, les paramètres sont transmis par défaut par référence : concrètement on passe un pointeur sur le début de la valeur, mais pas la valeur elle-même !
Il faut commencer à interpréter les prototypes des API en fonction du langage d’appel …
Le système étant écrit en C, certaines API utilisent la définition C d’une chaine de caractères : un pointeur sur le premier caractère, la fin de la chaîne étant marquée par le premier octet null !
En RPG, nous avons la fonction %str() qui permet de gérer ceci :
En CL, pas de fonction équivalent pour gérer cela.
Prenons par exemple l’API getEnv() (en fait une fonction de la bibliothèque standard C) :
Il faut fournir en entrée le nom de la variable d’environnement, au format C String, c’est à dire à terminaison nulle.
De même, la valeur de retour est un pointeur sur le début de la valeur. La fin se situe au premier octet null rencontré …
Voici un exemple d’appel :
Nous déclarons simplement une variable de type CHAR(1) initialisée à x’00’ :
Cela nous sert à créer la valeur pour l’appel : chaine à terminaison nulle contenant le nom de la variable d’environnement recherchée (ici CLASSPATH) :
CHGVAR &ENVVAR ( 'CLASSPATH' *CAT &SPC_INIT )
Pour décoder la valeur de retour, il nous faut parcourir la valeur reçue jusqu’à trouver la terminaison nulle. On utilise simplement %SCAN pour trouver la position et redécouper :
Au final, très peu de code à ajouter, mais nécessite une compréhension de la documentation des APIs, des types de données dans les différents langages, et des mécanismes de transmission de paramètres !
/wp-content/uploads/2017/05/logogaia.png00Habib Saad/wp-content/uploads/2017/05/logogaia.pngHabib Saad2022-10-13 12:45:402022-10-14 16:52:34Obtenir la définition de son écran
On est amené quand on fait des analyses à regarder les dates de source, on constate que ces dates sont à null pour tous les objets de type ILE.
Vous avez une vue QSYS2.PROGRAM_INFO qui permet d’avoir ces informations sur les programmes, un peu comme la commande DSPPGM.
Voici pourquoi : quand vous travaillez en OPM vous compilez des sources qui deviennent des programmes; quand vous travaillez en ILE, vous compilez des sources qui deviennent des modules, puis vous les assemblez pour créer des programmes et du coup une date de source sur un programme ILE ne veut rien dire.
En réalité un programme a un module qui s’appelle point d’entrée programme qui, quand on travaille en BND (CRTBND*), est le seul module placé dans qtemp qui est assemblé pour créer votre programme.
On voit donc que si on veut, on peut assimiler la date du source du programme à la date du module PEP, qui dans plus de 99 % des cas a le même nom que le programme. On a une deuxième vue permet d’avoir les modules par programme, QSYS2.BOUND_MODULE_INFO.
Il faudra donc combiner les 2 vues.
par exemple :
Pour les programmes ILE
SELECT a.PROGRAM_NAME, a.PROGRAM_TYPE, b.SOURCE_FILE_LIBRARY, b.SOURCE_FILE, b.SOURCE_FILE_MEMBER, b.SOURCE_CHANGE_TIMESTAMP FROM QSYS2.PROGRAM_INFO A join QSYS2.BOUND_MODULE_INFO B on a.PROGRAM_NAME = b.PROGRAM_NAME and A.PROGRAM_NAME = b.BOUND_MODULE and A.PROGRAM_LIBRARY = b.PROGRAM_LIBRARY WHERE a.PROGRAM_LIBRARY = ‘FADY’ and a.PROGRAM_TYPE = ‘ILE’
Pour les programmes OPM
SELECT a.PROGRAM_NAME, a.PROGRAM_TYPE, A.SOURCE_FILE_LIBRARY, A.SOURCE_FILE, A.SOURCE_FILE_MEMBER, A.SOURCE_FILE_CHANGE_TIMESTAMP FROM QSYS2.PROGRAM_INFO A WHERE a.PROGRAM_LIBRARY = ‘FADY’ and a.PROGRAM_TYPE = ‘OPM’
en faisant l’union des deux requêtes vous aurez les dates de tous vos programmes ILE et OPM.
Il y a sans doute d’autres solutions mais celle-ci est très simple à utiliser.
https://www.gaia.fr/wp-content/uploads/2022/08/IMG-20200712-WA0017.jpg1024768Ana Ramirez/wp-content/uploads/2017/05/logogaia.pngAna Ramirez2022-10-11 10:28:032022-10-14 10:15:33Date source de vos programmes
Une des difficultés, quand on développe avec VSCE sur IBMi , C’est que si on est 2 deux à modifier le même source, c’est le dernier qui a raison avec perte de modification du premier même s’il a sauvegardé
Voici comment on peut améliorer les choses. On va créer un fichier base de données qui liste les sources qui sont en cours de maintenance, un peu comme un ALM.
Avec GIT on peut arriver à des mécanismes identiques, et surtout, il faut commencer à mettre vos sources dans l’IFS directement
Voila comment, vous pouvez faire pour améliorer les choses
CREATE TABLE DB_OPENLCK (FICHIER CHAR ( 10) NOT NULL WITH DEFAULT, BIBLIO CHAR ( 10) NOT NULL WITH DEFAULT, MEMBRE CHAR ( 10) NOT NULL WITH DEFAULT, PARTAGE CHAR ( 3) NOT NULL WITH DEFAULT, PUSER CHAR ( 10) NOT NULL WITH DEFAULT, PDATE DATE NOT NULL WITH DEFAULT, PTIME TIME NOT NULL WITH DEFAULT)
Pour ajouter un source à verrouiller
INSERT INTO DB_OPENLCK VALUES(‘QRPGLESRC’, ‘GDATA’, ‘AAAA’, ‘NON’, ‘PLB’, current date, current time)
Et parmi les programmes d’exit il en a un qui va nous permettre de mettre en œuvre ce contrôle C’est le QIBM_QDB_OPEN
On va donc écrire un programme, ici en SQLRPGLE
**free
//
// ce programme permet d'éviter de travailler à 2 sur un même source
//
Dcl-Pi *N;
DS_parm likeds(ds_parm_t) ;
reponse int(10);
End-Pi;
// dsprogramme
dcl-ds *N PSDS ;
nom_du_pgm CHAR(10) POS(1);
init_user CHAR(10) POS(254);
enc_user CHAR(10) POS(358);
End-ds ;
// ds format DBOP0100
Dcl-DS ds_parm_t qualified template ;
taille_entete Int(10);
format Char(8);
offset_liste Int(10);
nbr_fichiers Int(10);
taille_liste Int(10);
job Char(10);
profil Char(10);
jobnbr Char(6);
cur_profil Char(10);
reste Char(1024);
End-DS;
// liste des fichiers dans notre cas un seul
Dcl-DS liste ;
fichier Char(10);
biblio Char(10);
membre Char(10);
filler Char(2);
typefichier Int(10);
sous_jacent Int(10);
access Char(4);
End-DS;
// variable de travail
Dcl-S partage char(4);
Dcl-S puser char(10);
ds_parm.offset_liste += 1;
dsply enc_user ;
liste = %subst(ds_parm : ds_parm.offset_liste :
ds_parm.taille_liste);
ds_parm.offset_liste += ds_parm.taille_liste;
// lecture des informations dans le fichier de verrouillage explicite
// le verrouillage est donc par utilisateur
exec sql
SELECT PARTAGE, PUSER into :partage , :puser
FROM DB_OPENLCK WHERE FICHIER = :FICHIER and BIBLIO
= :BIBLIO and MEMBRE = :MEMBRE ;
//
// La régle mise en oeuvre ici
// on autorise
// si même utilisateur
// si non trouvé en modification
// Si on on a dit partage à oui
//
if (sqlcode = 100 or partage = 'OUI' or puser = enc_user) ;
reponse = 1 ;
else ;
reponse = 0 ;
endif ;
// fin de programme
*inlr = *on;
ici notre règle est la suivante on autorise Si le source n’est pas présent dans le fichier Si l’utilisateur est le même que celui en cours Si on a accepté le partage et donc le risque
Quand on essaye d’accéder par VSCDE à notre source
Remarque
Le contrôle marche aussi avec RDI Il marche également pour SEU, parfois on préfère un contrôle spécifique SEU, vous devrez utiliser le programme d’exit QIBM_QSU_ALW_EDIT en utilisant le même fichier par exemple !
**free
//
// Ce programme eviter de travailler à 2 sur un même source
//
Dcl-Pi *N;
biblio char(10);
fichier char(10);
membre char(10);
reponse char(1);
End-Pi;
// dsprogramme
dcl-ds *N PSDS ;
nom_du_pgm CHAR(10) POS(1);
init_user CHAR(10) POS(254);
enc_user CHAR(10) POS(358);
End-ds ;
Dcl-S partage char(4);
Dcl-S puser char(10);
// lecture des informations dans le fichier de verrouillage explicite
// le verrouillage est donc par utilisateur
exec sql
SELECT PARTAGE, PUSER into :partage , :puser
FROM DB_OPENLCK WHERE FICHIER = :FICHIER and BIBLIO
= :BIBLIO and MEMBRE = :MEMBRE ;
//
// La règle mise en œuvre ici
// on autorise
// si même utilisateur
// si non trouvé en modification
// Si on on adit partage à oui
//
if (sqlcode = 100 or partage = 'OUI' or puser = enc_user) ;
reponse = '1' ;
else ;
reponse = '0' ;
endif ;
// fin de programme
*inlr = *on;
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2022-07-21 17:51:502024-03-26 15:58:28Verrouiller vos sources pour VSCODE
Vous pouvez désormais mettre des points d’exit pour savoir quand un fichier IFS est ouvert ou fermé QIBM_QP0L_OBJ_OPEN QIBM_QP0L_OBJ_CLOSE le format de data utilisé est le OBOP0100
exemple de programme en CLP
/*-------------------------------------------------------------------*/
/* exit pgm QIBM_QP0L_OBJ_OPEN FMT OBOP0100 */
/* Contrôle ouverture de fichier */
/*-------------------------------------------------------------------*/
pgm (&data &retour)
/* Paramètres */
dcl &data *char 512 /* Variable recue */
dcl &retour *char 4 /* Variable renvoyée */
/* 0 pour OK */
/* 1 pour KO */
/* Variables de travail */
DCL VAR(&USER) TYPE(*CHAR) STG(*DEFINED) LEN(10) +
DEFVAR(&DATA 1)
DCL VAR(&EXT) TYPE(*CHAR) STG(*DEFINED) LEN(8) +
DEFVAR(&DATA 11)
DCL VAR(&TYPE) TYPE(*CHAR) STG(*DEFINED) LEN(10) +
DEFVAR(&DATA 23)
DCL VAR(&FLAG) TYPE(*CHAR) STG(*DEFINED) LEN(4) +
DEFVAR(&DATA 28)
DCL VAR(&IDENT) TYPE(*CHAR) STG(*DEFINED) +
LEN(16) DEFVAR(&DATA 33)
DCL VAR(&PATHL) TYPE(*CHAR) STG(*DEFINED) LEN(4) +
DEFVAR(&DATA 49)
DCL VAR(&PATH) TYPE(*CHAR) STG(*DEFINED) +
LEN(256) DEFVAR(&DATA 53)
dcl &len *dec (5 0)
/* Conversion du path UTF16/UCS2 vers CCSID en cours */
CALL PGM(CVTUCS2) PARM((&PATH) (&PATH))
/* Longueur après conversion / 2 car UCS2 = 2 caractères */
chgvar &len (%BIN(&PATHL) / 2)
/*--------------------------------------------*/
/* Ici Votre traitement */
/*--------------------------------------------*/
SNDUSRMSG MSG('Fichier ' *BCAT %SST(&PATH 1 &LEN) +
*BCAT ', ouvert par ' *BCAT &USER) +
MSGTYPE(*INFO)
/*--------------------------------------------*/
/* Validation de la demande 0 pour OK */
/*--------------------------------------------*/
CHGVAR VAR(%BIN(&retour)) VALUE(0)
endpgm
pour l'attachement du programme au point d'exit
ADDEXITPGM EXITPNT(QIBM_QP0L_OBJ_OPEN)
FORMAT(OBOP0100)
PGMNBR(1)
PGM(PLB/PGMIFS)
THDSAFE(*YES)
REPLACE(*NO)
attention à bien mettre le paramètre THDSAFE(*YES)
Remarque : Le path du fichier est déclaré en UCS2 ci joint un petit programme de conversion en RPGLE , utile si vous avez choisi d’écrire votre programme en CLLE
**free
// Programme de conversion CVTUCS2
// utf16/UCS2 vers ccsid en cours par défaut
Dcl-pi *N ;
I_zon ucs2(256) ; // soit une chaine de 128
O_zon char(256) ;
End-pi ;
O_zon = I_zon ;
*inlr = *on ;
Pour être analysé par le point d’exit vos fichiers doivent avoir l’attribut *RUNEXIT
Une des raisons est que les index peuvent être beaucoup plus performants que les LF quand le moteur SQL les utilise.
Rappel Pour transformer un PF en table
Vous devez extraire le source en utilisant l’API QSQGNDDL Le plus simple est de passer par ACS En faisant génération instruction SQL
Vous obtenez le source SQL qu’il aurait fallu pour générer cette table.
Attention tout n’est pas traduit (exemple un PF sans clé unique)
Pour transformer un LF en index sur nom par exemple
Si vous utilisez ACS, votre index est considéré comme une vue et si vous faites l’opération de génération SQL vous obtenez un source qui ne va pas vous servir à grand chose. Remarque, par contre si vous regardez par Visual Explain vous voyez bien que le moteur utilise le PF comme un index.
Si vous utilisez la procédure de QSYS2.GENERATE_SQL, même problème.
.
Si vous lui indiquez index, il ne trouve pas l’objet SQL
Out of the GENERATE_SQL documentation: INDEX_INSTEAD_OF_VIEW – option: The index instead of view option specifies whether a CREATE INDEX or CREATE VIEW statement will be generated for a DDS-created keyed logical file. The valid values are:
0 – A CREATE VIEW statement will be generated. 1 – A CREATE INDEX statement will be generated that matches the index for a DDS-created keyed logical file.
ADDITONAL_INDEX_OPTION: The additional index option specifies whether additional CREATE INDEX statements will be generated for DDS-created keyed physical or logical files. The valid values are:
0 – Additional CREATE INDEX statements will not be generated. 1 – An additional CREATE INDEX statement will be generated that matches the index for a DDS-created keyed physical file. If the physical file has a PRIMARY KEY constraint, a CREATE INDEX statement is not generated. An additional CREATE INDEX statement will be generated that matches the index for a DDS-created keyed logical file. If a value of ‘1’ is specified for the index instead of view option, an additional CREATE INDEX statement is not generated. Additional CREATE INDEX statements will also be generated that match the join indexes of a DDS-created join logical file.
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2022-04-21 10:44:222022-04-26 14:41:31Transformation LF en index
Sur votre système, il peut rester des logs à l’état pending, ce n’est pas normal, c’est des logs qui ne sont pas accessibles, mais qui sont là …
Vous pouvez facilement regarder cette information grâce à la vue QSYS2.SYSTEM_STATUS_INFO
Vous devez d’abord vérifier la valeur système qui indique la production de ces logs. c’est QLOGOUTPUT qui doit être à *JOBLOGSVR et non à *PND qui indiquerait au système de les laisser dans cet état là.
Pour supprimer ces spools inutiles vous devrez utiliser l’API QWTRMVJL
Voici un exemple d’utilisation vous pouvez la passer comme ceci