/
Nouveau venu dans les bibliothèques middleware pour IBMi, MAPEPIRE est un outil simple pour récupérer des données de votre serveur et les travailler sur de applications tierces, telles que des outils d’analyse de données, de la bureautique, etc.
Nous allons vous présenter la possibilité d’installer et d’utiliser le produit simplement
- sur le serveur
- sur votre client, en fonction du langage que vous souhaitez utiliser.
- Les langages disponibles pour l’instant sont :
- JAVA, NODE.JS, PYTHON
Ici, l’exemple détaillé sera effectué avec le langage PYTHON.
Nous n’intervenons pas dans cet article sur les différents paramétrages de l’outil. Nous y reviendrons dans un article suivant. (exit points, ports, etc.)
Serveur
Installation de MAPEPIRE sur le serveur
yum install mapepire
mapepire sera installé dans le répertoire
/qOpenSys/pkgs/bin
Démarrage
Note : dans cet article, on ne détaille ps le démarrage automatique
nohup /qopensys/pkgs/bin/mapepire &
Client
Notre exemple consiste à lister tous les travaux actifs en cours, les répertorier dans une trame PANDAS, puis de sauvegarder les données dans une feuille EXCEL
Pré requis
- Python 3 installé et fonctionnel
- un répertoire pour le code
- Facultatif : un environnement virtuel
- EXCEL
- librairies installées :
- pandas
- openpyxl (factultatif)
installation MAPEPIRE
sous l’environnement virtuel (si configuré) ou sur l’environnement global
pip install mapepire-python
le code de notre exemple TEST.PY
#mapepire
#mapepire
from mapepire_python.client.sql_job import SQLJob
from mapepire_python import DaemonServer
#pandas
import pandas as pd
#--------------------------------------------------
creds = DaemonServer(
host="serveuràcontacter",
port=8076,
user="utilisateur",
password='motdepasse',
ignoreUnauthorized=True,
)
job = SQLJob()
res = job.connect(creds)
#
# Travaux actifs
#
result = job.query_and_run("\
SELECT \
count(*) as totaltravaux\
FROM TABLE (QSYS2.ACTIVE_JOB_INFO()) \
")
countjobs = result['data'][0]['TOTALTRAVAUX']
startT = datetime.now()
result = job.query_and_run("SELECT \
JOB_NAME, JOB_TYPE, JOB_STATUS, \
SUBSYSTEM, MEMORY_POOL, THREAD_COUNT \
FROM TABLE ( \
QSYS2.ACTIVE_JOB_INFO(\
RESET_STATISTICS => 'NO',\
SUBSYSTEM_LIST_FILTER => '',\
JOB_NAME_FILTER => '*ALL',\
CURRENT_USER_LIST_FILTER => '',\
DETAILED_INFO => 'NONE'\
)\
) \
ORDER BY \
SUBSYSTEM, RUN_PRIORITY, JOB_NAME_SHORT, JOB_NUMBER\
",
rows_to_fetch=countjobs)
endT = datetime.now()
delta = endT - startT
print(f"travaux actifs récupérés en {str(delta)} secondes")
#insertion des résultats dans un Frame PANDAS
dframActj = pd.DataFrame(result['data'])
#print(dframActj)
#
#récupération des utilisateurs dans une 2ème Frame (dframUsesrs)
#
startT = datetime.now()
result = job.query_and_run("""
WITH USERS AS (
SELECT
CASE GROUP_ID_NUMBER
WHEN 0 THEN 'USER'
ELSE 'GROUP'
END AS PROFILE_TYPE,
A.*,
CAST(TEXT_DESCRIPTION AS VARCHAR(50) CCSID 1147)
AS TEXT_DESCRIPTION_CASTED
FROM (
SELECT *
FROM QSYS2.USER_INFO
) AS A
)
SELECT *
FROM USERS
""",
rows_to_fetch=500)
endT = datetime.now()
delta = endT - startT
print(f"Utilisateurs récupérés en {str(delta)} secondes")
#insertion des résultats dans un Frame PANDAS
dframUsers = pd.DataFrame(result['data'])
#print(dframUsers)
print("Sauvegarde vers Excel")
with pd.ExcelWriter('/users/ericfroehlicher/Documents/donnes_dataframe.xlsx') as writer:
dframActj.to_excel(writer, sheet_name='ACTjobs')
dframUsers.to_excel(writer, sheet_name='Utilisateurs')
Un peu d’explications
1 – Import des resources dont on a besoin
#mapepire
from mapepire_python.client.sql_job import SQLJob
from mapepire_python import DaemonServer
#pandas
import pandas as pd
2 – Déclaration des données de connexion (serveur, utilisateur, mot def passe)
CONSEIL: pour l’instant, toujours laisser le port 8076
#--------------------------------------------------
creds = DaemonServer(
host="serveuràcontacter",
port=8076,
user="utilisateur",
password='motdepasse',
ignoreUnauthorized=True,
)
P
3 – connexion au serveur
job = SQLJob()
res = job.connect(creds)
Ici, on crée un travail simple, synchrone (SQLJob)
4 – les requêtes synchrones
#comptage des travaux (pour l'exemple de l'utilisation du json)
result = job.query_and_run("\
SELECT \
count(*) as totaltravaux\
FROM TABLE (QSYS2.ACTIVE_JOB_INFO()) \
")
# je récupère directement la valeur lue
countjobs = result['data'][0]['TOTALTRAVAUX']
result = job.query_and_run("SELECT \
JOB_NAME, JOB_TYPE, JOB_STATUS, \
SUBSYSTEM, MEMORY_POOL, THREAD_COUNT \
FROM TABLE ( \
QSYS2.ACTIVE_JOB_INFO(\
RESET_STATISTICS => 'NO',\
SUBSYSTEM_LIST_FILTER => '',\
JOB_NAME_FILTER => '*ALL',\
CURRENT_USER_LIST_FILTER => '',\
DETAILED_INFO => 'NONE'\
)\
) \
ORDER BY \
SUBSYSTEM, RUN_PRIORITY, JOB_NAME_SHORT, JOB_NUMBER\
",
rows_to_fetch=countjobs)
A
Les données obtenues sont au format JSON. (voir plus bas les données brutes)
5 – Insertion des données dans un frame PANDAS et sauvegarde vers EXCEL
#insertion des résultats dans un Frame PANDAS
dframe = pd.DataFrame(result['data'])
print(dframe)
print("Sauvegarde vers Excel")
dframe.to_excel(
"/users/ericfroehlicher/Documents/travaux_actifs.xlsx",
sheet_name="Travaux actifs",
index=False
)
Retour de mapepire
Le flux de données renvoyé par MAPEPIRE contient l’ensemble des données et méta données au format JSON.
Voici un extrait du flux retourné (exemple sur 5 travaux)
{
'id': 'query4',
'has_results': True,
'update_count': -1,
'metadata':
{
'column_count': 6,
'job': '488835/QUSER/QZDASOINIT',
'columns':[
{
'name': 'JOB_NAME',
'type': 'VARCHAR',
'display_size': 28,
'label': 'JOB_NAME'
},
{
'name': 'JOB_TYPE',
'type': 'VARCHAR',
'display_size': 3,
'label': 'JOB_TYPE'
},
{
'name': 'JOB_STATUS',
'type': 'VARCHAR',
'display_size': 4,
'label': 'JOB_STATUS'
},
{
'name': 'SUBSYSTEM',
'type': 'VARCHAR',
'display_size': 10,
'label': 'SUBSYSTEM'
},
{
'name': 'MEMORY_POOL',
'type': 'VARCHAR',
'display_size': 9,
'label': 'MEMORY_POOL'
},
{
'name': 'THREAD_COUNT',
'type': 'INTEGER',
'display_size': 11,
'label': 'THREAD_COUNT'
}
]
},
'data':[
{
'JOB_NAME': '216350/QSYS/ARCAD',
'JOB_TYPE': 'SBS',
'JOB_STATUS': 'DEQW',
'SUBSYSTEM': 'ARCAD',
'MEMORY_POOL': 'BASE',
'THREAD_COUNT': 2
},
{
'JOB_NAME': '216369/ARCAD_NET/ARCAD',
'JOB_TYPE': 'ASJ',
'JOB_STATUS': 'MSGW',
'SUBSYSTEM': 'ARCAD',
'MEMORY_POOL': 'BASE',
'THREAD_COUNT': 1
},
{
'JOB_NAME': '216349/QSYS/CONTROL4I',
'JOB_TYPE': 'SBS',
'JOB_STATUS': 'DEQW',
'SUBSYSTEM': 'CONTROL4I',
'MEMORY_POOL': 'BASE',
'THREAD_COUNT': 2
},
{
'JOB_NAME': '216373/CTL4I/CTAGENTSPW',
'JOB_TYPE': 'PJ',
'JOB_STATUS': 'PSRW',
'SUBSYSTEM': 'CONTROL4I',
'MEMORY_POOL': 'BASE',
'THREAD_COUNT': 1
},
{
'JOB_NAME': '216377/CTL4I/CTAGENTSPW',
'JOB_TYPE': 'PJ',
'JOB_STATUS': 'PSRW',
'SUBSYSTEM': 'CONTROL4I',
'MEMORY_POOL': 'BASE',
'THREAD_COUNT': 1
}
],
'is_done': False,
'success': True
}
Résultats

