Compare commits

..

10 Commits

Author SHA1 Message Date
Sven Riwoldt
e06c448a46 Idoit-Tests 01 2024-12-15 14:38:48 +01:00
16d9b8bd2c Update CMDB_vars.json 2024-12-09 14:54:12 +00:00
de66396908 Nun funktioniert es 2024-12-09 14:19:01 +00:00
b2946a4c59 Beim JSON kollabiert es 2024-12-09 14:00:52 +00:00
6a34b20dab Json Kommentare ausgelagert 2024-12-09 13:32:10 +00:00
4aee433aea Beginn neue Datei 2024-12-05 13:20:27 +00:00
3383dcf75f AM2CSV.ui ersetzen 2024-12-05 13:19:38 +00:00
2be7f08b1c Auskommentierungen damit ich erst einmal weiter importieren kann 2024-11-26 14:41:13 +00:00
16f4ad4463 Neue Oberfläche 2024-11-26 10:40:47 +00:00
55627e198f Update CMDB2CSV_Aufbaumaster.py 2024-11-25 15:00:30 +00:00
56 changed files with 1464 additions and 14 deletions

110
AM2CSV.ui Normal file
View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Aufbaumaster2CSV</class>
<widget class="QDialog" name="Aufbaumaster2CSV">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>701</width>
<height>192</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QPushButton" name="pB_open">
<property name="geometry">
<rect>
<x>260</x>
<y>20</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Öffnen</string>
</property>
</widget>
<widget class="QPushButton" name="pB_save">
<property name="geometry">
<rect>
<x>260</x>
<y>70</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Speichern</string>
</property>
</widget>
<widget class="QLabel" name="lb_aufbaumaster">
<property name="geometry">
<rect>
<x>50</x>
<y>20</y>
<width>151</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Auswahl Aufbaumaster</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>50</x>
<y>70</y>
<width>151</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>CSV speichern</string>
</property>
</widget>
<widget class="QLabel" name="lb_selected_aufbaumaster">
<property name="geometry">
<rect>
<x>360</x>
<y>20</y>
<width>331</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>50</x>
<y>130</y>
<width>114</width>
<height>42</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="rB_gg">
<property name="text">
<string>nur Grundgeräte</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rB_erweiterungen">
<property name="text">
<string>nur Erweiterungen</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

26
Api01.py Normal file
View File

@@ -0,0 +1,26 @@
from typing import List
from idoit_scaleup.base import IDoitApiBase
from idoit_scaleup import createApiCalls
from idoit_scaleup import consts
import json
config_file = 'api.json'
# Test Abfrage der IP-Adressen
OBJ_ID = 3518
f = open(config_file)
cfg = json.load(f)
idoit_apis = createApiCalls(cfg)
api = idoit_apis[consts.C__CATG__IP]
api.set_debug_mode()
#rtn=api.read_categories(OBJ_ID)
rtn=api.get_all()
print(json.dumps(rtn))

View File

@@ -6,6 +6,7 @@ import pandas as pd
from icecream import ic from icecream import ic
import numpy as np import numpy as np
import json import json
import logging
class MainUI(QDialog): # erbt von QDialog class MainUI(QDialog): # erbt von QDialog
@@ -13,7 +14,21 @@ class MainUI(QDialog): # erbt von QDialog
# super (MainUI, self).__init__() #Aufrufen des Konstruktors von QDialog # super (MainUI, self).__init__() #Aufrufen des Konstruktors von QDialog
super().__init__() super().__init__()
loadUi("Aufbaumaster2CSV.ui", self) loadUi("Aufbaumaster2CSV.ui", self)
self.logger = logging.getLogger("Aufbaumaster2CSV")
self.logger.setLevel(logging.DEBUG)
self.log_file = "aufbaumaster2csv.log"
self.file_handler = logging.FileHandler(self.log_file)
self.file_handler.setLevel(logging.DEBUG)
self.formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
self.file_handler.setFormatter(self.formatter)
if not self.logger.hasHandlers():
self.logger.addHandler(self.file_handler)
self.filename = None self.filename = None
self.onlyfilename = None
self.path = None self.path = None
self.df_vte = None self.df_vte = None
self.df_cmdb = None self.df_cmdb = None
@@ -40,6 +55,10 @@ class MainUI(QDialog): # erbt von QDialog
self.data = json.load(file) self.data = json.load(file)
print(self.data) print(self.data)
# def do_something(self):
# MainUI.logger.debug("Debugging info...")
def open_file_dialog(self): def open_file_dialog(self):
self.filename, _ = QFileDialog.getOpenFileName( self.filename, _ = QFileDialog.getOpenFileName(
self, self,
@@ -52,19 +71,31 @@ class MainUI(QDialog): # erbt von QDialog
if self.filename: if self.filename:
self.path = Path(self.filename) self.path = Path(self.filename)
self.onlyfilename = os.path.basename(self.filename)
self.collect_allgemein() self.collect_allgemein()
self.collect_cmdb_daten_gg() self.collect_cmdb_daten_gg()
self.collect_cmdb_daten_erw() self.collect_cmdb_daten_erw()
self.collect_vm() #self.collect_vm()
def collect_vm(self): def collect_vm(self):
self.df_vte_vm= self.df_vte[self.df_vte['Gruppierung'] == 'VM'] self.df_vte_vm= self.df_vte[self.df_vte['Gruppierung'] == 'VM']
if self.df_vte_vm.empty:
self.logger.info("Aufbaumaster %s hat keine VMs! - Beendung des Programms",self.onlyfilename)
#sys.exit(0)
self.df_cmdb_vm = self.df_cmdb[self.df_cmdb['Filter'] == 'VM'] self.df_cmdb_vm = self.df_cmdb[self.df_cmdb['Filter'] == 'VM']
self.df_vte_vm = self.df_vte_vm.apply(lambda x: x.str.lstrip() if x.dtype == "object" else x) self.df_vte_vm = self.bereinigen_leerzeichen(self.df_vte_vm)
self.df_cmdb_vm = self.df_cmdb_vm.apply(lambda x: x.str.lstrip() if x.dtype == "object" else x) self.df_cmdb_vm = self.bereinigen_leerzeichen(self.df_cmdb_vm)
self.df_cmdb_vm = self.df_cmdb_vm.drop(columns=['WV-Start', 'WV-Ende', 'CMDB-Status', 'Aufgabe Schritt', 'Filter', 'Waermeabgabe [BTU/h]','kalk. Strom [A]'])
ic(self.df_vte_vm)
ic(self.df_cmdb_vm)
def bereinigen_leerzeichen(self, df):
return df.apply(lambda x: x.str.lstrip() if x.dtype == "object" else x)
def collect_cmdb_daten_gg(self): def collect_cmdb_daten_gg(self):
# Einlesen der Sheets allgemein # Einlesen der Sheets allgemein
@@ -77,9 +108,10 @@ class MainUI(QDialog): # erbt von QDialog
# Führende Leerzeichen in allen Spalten entfernen # Führende Leerzeichen in allen Spalten entfernen
self.df_vte_gg = self.df_vte_gg.apply(lambda x: x.str.lstrip() if x.dtype == "object" else x) self.df_vte_gg = self.bereinigen_leerzeichen(self.df_vte_gg)
self.df_cmdb_gg = self.df_cmdb_gg.apply(lambda x: x.str.lstrip() if x.dtype == "object" else x) self.df_cmdb_gg = self.bereinigen_leerzeichen(self.df_cmdb_gg)
# Teil Grundgeräte # Teil Grundgeräte
self.df_cmdb_gg = self.df_cmdb_gg.drop( self.df_cmdb_gg = self.df_cmdb_gg.drop(
columns=['WV-Start', 'WV-Ende', 'CMDB-Status', 'Aufgabe Schritt', 'Filter', 'Waermeabgabe [BTU/h]', columns=['WV-Start', 'WV-Ende', 'CMDB-Status', 'Aufgabe Schritt', 'Filter', 'Waermeabgabe [BTU/h]',
@@ -142,7 +174,7 @@ class MainUI(QDialog): # erbt von QDialog
# Setzen von int für HE und Anz. HE # Setzen von int für HE und Anz. HE
self.dfb_gg['HE'] = self.dfb_gg['HE'].apply(lambda x: x if pd.isnull(x) else str(int(x))) #self.dfb_gg['HE'] = self.dfb_gg['HE'].apply(lambda x: x if pd.isnull(x) else str(int(x)))
def has_special_characters(self, s): def has_special_characters(self, s):
# Regex pattern für Sonderzeichen # Regex pattern für Sonderzeichen
@@ -400,14 +432,13 @@ class MainUI(QDialog): # erbt von QDialog
def collect_cmdb_daten_erw(self): def collect_cmdb_daten_erw(self):
############## Erweiterung ################################################################################ ############## Erweiterung ################################################################################
# Kopieren
self.df_vte_erw = self.df_vte
self.df_cmdb_erw = self.df_cmdb
# Führende Leerzeichen in allen Spalten entfernen # Führende Leerzeichen in allen Spalten entfernen
self.df_vte_erw = self.df_vte_erw.apply(lambda x: x.str.lstrip() if x.dtype == "object" else x) self.df_vte_erw = self.bereinigen_leerzeichen(self.df_vte_erw)
self.df_cmdb_erw = self.df_cmdb_erw.apply(lambda x: x.str.lstrip() if x.dtype == "object" else x) self.df_cmdb_erw = self.bereinigen_leerzeichen(self.df_cmdb_erw)
# Auffüllen der Spalte Hostname # Auffüllen der Spalte Hostname
self.df_vte_erw['Hostname']= self.df_vte_erw['Hostname'].replace('', np.nan) self.df_vte_erw['Hostname']= self.df_vte_erw['Hostname'].replace('', np.nan)
@@ -540,7 +571,8 @@ class MainUI(QDialog): # erbt von QDialog
self.dfb_gg.to_csv(os.path.splitext(os.path.basename(self.savefilename))[0]+"_GG"+os.path.splitext(os.path.basename(self.savefilename))[1], index=None, header=True, encoding='utf-8') self.dfb_gg.to_csv(os.path.splitext(os.path.basename(self.savefilename))[0]+"_GG"+os.path.splitext(os.path.basename(self.savefilename))[1], index=None, header=True, encoding='utf-8')
self.dfb_erw.to_csv(os.path.splitext(os.path.basename(self.savefilename))[0]+"_ERW"+os.path.splitext(os.path.basename(self.savefilename))[1], index=None, header=True, encoding='utf-8') self.dfb_erw.to_csv(os.path.splitext(os.path.basename(self.savefilename))[0]+"_ERW"+os.path.splitext(os.path.basename(self.savefilename))[1], index=None, header=True, encoding='utf-8')
# print("Datei wurde gespeichert:", self.savefilename) #self.dfb_vm.to_csv(os.path.splitext(os.path.basename(self.savefilename))[0]+"_VM"+os.path.splitext(os.path.basename(self.savefilename))[1], index=None, header=True, encoding='utf-8')
print("Datei wurde gespeichert:", self.savefilename)
def collect_allgemein(self): def collect_allgemein(self):
self.df_vte = pd.read_excel(self.filename, header=7, na_filter=False, sheet_name='VTE-Input', self.df_vte = pd.read_excel(self.filename, header=7, na_filter=False, sheet_name='VTE-Input',
@@ -548,6 +580,10 @@ class MainUI(QDialog): # erbt von QDialog
self.df_cmdb = pd.read_excel(self.filename, header=2, sheet_name="CMDB", engine='pyxlsb') self.df_cmdb = pd.read_excel(self.filename, header=2, sheet_name="CMDB", engine='pyxlsb')
# Kopieren
self.df_vte_erw = self.df_vte
self.df_cmdb_erw = self.df_cmdb
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)
ui = MainUI() ui = MainUI()

View File

@@ -0,0 +1,87 @@
from PyQt5.QtWidgets import QApplication, QDialog, QFileDialog
from PyQt5.uic import loadUi
import sys, os, re
from pathlib import Path
import pandas as pd
from icecream import ic
import numpy as np
import json
import logging
class A2CSV(QDialog): # erbt von QDialog
def __init__(self):
super().__init__()
loadUi("AM2CSV.ui", self)
self.pB_open.clicked.connect(self.open_file_dialog)
self.filename = None
self.onlyfilename = None
self.path = None
self.vte = None
self.cmdb = None
self.gg = self.rB_gg
self.gg.toggled.connect(self.radio_button_activated)
self.erw = self.rB_erweiterungen
self.erw.toggled.connect(self.radio_button_activated)
self.vte_gg = None
self.cmdb_gg = None
self.jdata = None
self.objecttypes: list = []
self.read_json()
self.objecttypes = self.jdata["Objekttyp"]
ic(self.objecttypes)
def read_json(self):
with open("CMDB_vars.json", "r") as file:
self.jdata = json.load(file)
ic(self.jdata)
def open_file_dialog(self):
# Nur xlsb
self.filename, _ = QFileDialog.getOpenFileName(self,"Aufbaumaster","\\Volumes\\Daten01\\Documents\\toCSV","Excel (*.xlsb)")
if self.filename:
self.path = Path(self.filename)
self.onlyfilename = os.path.basename(self.filename)
self.lb_selected_aufbaumaster.setText(self.onlyfilename)
self.collect_data()
def collect_data(self):
# Reiter VTE und CMDB
# VTE "nur" für die Config-ID
self.vte = pd.read_excel(self.filename, header=7, na_filter=False, sheet_name='VTE-Input',usecols=['Hostname', 'Gruppierung', 'CONFIG-ID', 'CMDB Status'], engine='pyxlsb')
self.cmdb = pd.read_excel(self.filename, header=2, sheet_name="CMDB", engine='pyxlsb')
ic(self.vte)
ic(self.cmdb)
def collect_gg(self):
# Nach relevanten Spalten filtern Grundgeraete
# Sheet VTE
self.vte_gg = self.vte[self.vte['Gruppierung'] == 'Grundgerät']
# Sheet CMDB
self.cmdb_gg = self.cmdb[self.cmdb['Filter'] == 'Grundgerät']
def radio_button_activated(self):
if self.gg.isChecked():
self.collect_gg()
ic(self.vte_gg)
elif self.erw.isChecked():
ic("erw")
if __name__ == "__main__":
app = QApplication(sys.argv)
ui = A2CSV()
ui.show()
app.exec_()

View File

@@ -8,10 +8,41 @@
}, },
{ {
"Paketfilter / ALG": "C__OBJTYPE__APPLIANCE" "Paketfilter / ALG": "C__OBJTYPE__APPLIANCE"
} , },
{ {
"Kryptierer": "C__OBJTYPE__SD_KRYPTIERER" "Kryptierer": "C__OBJTYPE__SD_KRYPTIERER"
} },
{
"Server": "C__OBJTYPE__SERVER"
},
{
"Switch": "C__OBJTYPE__SWITCH"
},
{
"virtuelle Maschine": "C__OBJTYPE__VIRTUAL_SERVER"
},
{
"Terminalserver": "C__OBJTYPE__TERMINALSERVER"
},
{
"Storage": "C__OBJTYPE__SAN"
},
{
"SFP": "C__OBJTYPE__SD_SFP"
},
{
"Speichersystem": "C__OBJTYPE__SAN"
},
{
"Router": "C__OBJTYPE__ROUTER"
}
],
"Hersteller":
[
{"cisco":"Cisco Systems"},
{"genua":"genua GmbH"},
{"digi":"Digi International Inc."}
] ]
} }

5
Notiz_fuer_json.txt Normal file
View File

@@ -0,0 +1,5 @@
_comment 10G Base Active Optical SFP + Cable 3m --> SFP+ 10GBase-SR - LR
__note 10G Base Active Optical SFP + Cable 3m --> SFP+ 10GBase-SR - LR
__comment ET DX200S5 Base 2.5 <-- ET DX200S5 Base 2.5 Standard
__comment ET DX200S5 Base 3.5 <-- ET DX200S5 Base 3.5 Standard

6
api.json Normal file
View File

@@ -0,0 +1,6 @@
{
"api_key": "c1ia5q",
"user": "admin",
"password" : "admin",
"jrpc_url": "https://demo.i-doit.com/src/jsonrpc.php"
}

90
idoit_scaleup/__init__.py Executable file
View File

@@ -0,0 +1,90 @@
from .object import IDoitObject
from . import consts
from pprint import pprint
from .cat_access import IDoitAccess
from .cat_application import IDoitApplication
from .cat_connector import IDoitConnector
from .cat_cpu import IDoitCpu
from .cat_ip import IDoitIP
from .cat_location import IDoitLocation
from .cat_memory import IDoitMemory
from .cat_network import IDoitNetwork
from .cat_networkport import IDoitNetworkPort
from .cat_network_log_port import IDoitNetworkLogicalPort
from .cat_power_consumer import IDoitPowerConsumer
#from .cat_racktables import Racktables
from .cat_vlan import IDoitVlan
from .category import IDoitCategory
from .conditional_read import IDoitConditionalRead
from .dialog import IDoitDialog
from .search import IDoitSearch
from .cat_storage_device import IDoitStorageDevice
from .api_log import IDoitApiLog
import sys
import inspect
def createApiCall(cfg, category):
current_module = sys.modules[__name__]
for name, obj in inspect.getmembers(current_module):
if inspect.isclass(obj):
if issubclass(obj, IDoitCategory):
try:
found = False
found = (obj.CATEGORY == category)
if found:
return obj(cfg)
except AttributeError:
pass
if category.startswith('C__OBJTYPE__'):
return IDoitObject(cfg, category)
if category.startswith('C__CATS__') or category.startswith('C__CATG__'):
return IDoitCategory(cfg, category)
return None
def createApiCalls(cfg):
rtn = {}
for varname in consts.__dict__.keys():
if not (varname in rtn.keys()):
rtn[varname] = createApiCall(cfg, varname)
return rtn
def createApiDialogs(cfg, category, field):
if 'dialogs' not in cfg.keys():
cfg['dialogs'] = {}
if category not in cfg['dialogs'].keys():
cfg['dialogs'][category] = {}
if field not in cfg['dialogs'][category].keys():
cfg['dialogs'][category][field] = IDoitDialog(cfg, category, field)
return cfg['dialogs'][category][field]
def search(cfg) -> IDoitSearch:
return IDoitSearch(cfg)
def conditional_read(cfg) -> IDoitConditionalRead:
return IDoitConditionalRead(cfg)
def get_all_classes():
rtn = []
current_module = sys.modules[__name__]
for name, obj in inspect.getmembers(current_module):
if inspect.isclass(obj):
rtn.append(name)
return rtn
def turn_on_api_logging():
IDoitApiLog.instance().turn_on()
def turn_off_api_logging():
IDoitApiLog.instance().turn_off()
def get_api_log():
return IDoitApiLog.instance().get_api_log()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

30
idoit_scaleup/api_log.py Executable file
View File

@@ -0,0 +1,30 @@
class IDoitApiLog:
_instance = None
def __init__(self):
raise RuntimeError('Call instance() instead')
@classmethod
def instance(cls):
if cls._instance is None:
cls._instance = cls.__new__(cls)
cls.log = []
cls.do_log = False
# Put any initialization here.
return cls._instance
def turn_on(cls):
cls.do_log = True
def append_api_log(cls, url: str, payload, response):
if cls.do_log:
cls.log.append({
'url': url,
'payload': payload,
'response': response
})
def get_api_log(cls):
return cls.log

54
idoit_scaleup/base.py Executable file
View File

@@ -0,0 +1,54 @@
import json
import requests
from pprint import pprint
from .api_log import IDoitApiLog
from json.decoder import JSONDecodeError
class IDoitApiBase:
def __init__(self, cfg):
self.cfg = cfg
self.debug = False
def set_debug_mode(self, debug=True):
self.debug = debug
def xml_rpc_call(self, method, params, debug=False):
headers = {'content-type': 'application/json'}
payload = {
"method": method,
"params": params,
"jsonrpc": "2.0",
"id": 1,
}
basic_auth = (self.cfg['user'], self.cfg['password'])
params['apikey'] = self.cfg['api_key']
try:
response = requests.post(
self.cfg['jrpc_url'],
data=json.dumps(payload),
auth=basic_auth,
headers=headers
).json()
except JSONDecodeError:
print('JSON DECODE ERROR')
print('Url')
print(self.cfg['jrpc_url'])
print('Payload')
payload['params']['apikey'] = 'xxx'
pprint(payload)
response = {}
IDoitApiLog.instance().append_api_log(
self.cfg['jrpc_url'], payload, response)
if self.debug or debug or 'error' in response.keys():
print('Url')
print(self.cfg['jrpc_url'])
print('Payload')
payload['params']['apikey'] = 'xxx'
pprint(payload)
print('Resonse')
pprint(response)
return response

13
idoit_scaleup/cat_access.py Executable file
View File

@@ -0,0 +1,13 @@
from .consts import C__CATG__ACCESS
from .category import IDoitCategory
class IDoitAccess(IDoitCategory):
CATEGORY = C__CATG__ACCESS
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_primary(self, data):
return int(data['primary']['value'])

View File

@@ -0,0 +1,42 @@
from .consts import C__CATG__APPLICATION
from .category import IDoitCategory
from copy import deepcopy
class IDoitApplication(IDoitCategory):
CATEGORY = C__CATG__APPLICATION
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
# FIXME Skip, must be implemented later
def convert_field_with_name_assigned_license(self, data):
return 0
# FIXME Skip, must be implemented later
def convert_field_with_name_assigned_database_schema(self, data):
return 0
# FIXME Skip, must be implemented later
def convert_field_with_name_assigned_it_service(self, data):
return 0
def convert_field_with_name_assigned_version(self, data):
return int(data['assigned_version']['ref_id'])
def convert_field_with_name_bequest_nagios_services(self, data):
return int(data['bequest_nagios_services']['value'])
# def fix_obj(self, cdata):
# if ('assigned_version' in cdata.keys()) and (cdata['assigned_version'] is not None):
# cdata['assigned_version'] = str(cdata['assigned_version'])
# def save_category(self, objId, data):
# cdata = deepcopy(data)
# self.fix_obj(cdata)
# return super().save_category(objId, cdata)
# def update_category(self, objId, data):
# cdata = deepcopy(data)
# self.fix_obj(cdata)
# return super().update_category(objId, cdata)

31
idoit_scaleup/cat_connector.py Executable file
View File

@@ -0,0 +1,31 @@
from .consts import C__CATG__CONNECTOR
from .category import IDoitCategory
from pprint import pprint
class IDoitConnector(IDoitCategory):
CATEGORY = C__CATG__CONNECTOR
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_assigned_category(self, data):
return data['assigned_category']['const']
def convert_field_with_name_assigned_connector(self, data):
return self.conv_array_field('assigned_connector', data, 'ref_id')
def convert_field_with_name_cable_connection(self, data):
return self.conv_array_field('cable_connection', data, 'id')
def convert_field_with_name_relation_direction(self, data):
return int(data['relation_direction']['id'])
def convert_field_with_name_connector_sibling(self, data):
return int(data['connector_sibling']['id'])
def save_category_if_changed(self, objId, data):
raise Exception(
'Funktioniert nur wenn es nur eine Kategorie gibt, ' +
'muss mit ID spezifiziert werden')

13
idoit_scaleup/cat_cpu.py Executable file
View File

@@ -0,0 +1,13 @@
from .consts import C__CATG__CPU
from .category import IDoitCategory
class IDoitCpu(IDoitCategory):
CATEGORY = C__CATG__CPU
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_frequency(self, data):
return float(data['frequency']['title'])

41
idoit_scaleup/cat_ip.py Executable file
View File

@@ -0,0 +1,41 @@
from .consts import C__CATG__IP
from .category import IDoitCategory
class IDoitIP(IDoitCategory):
CATEGORY = C__CATG__IP
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_primary(self, data):
if data['primary']['value']==None:
return False
return int(data['primary']['value'])
def convert_field_with_name_active(self, data):
if data['active']['value']==None:
return False
return int(data['active']['value'])
def convert_field_with_name_use_standard_gateway(self, data):
if data['use_standard_gateway']['value']==None:
return False
return int(data['use_standard_gateway']['value'])
def convert_field_with_name_ipv4_address(self, data):
return data['ipv4_address']['ref_title']
def convert_field_with_name_ipv6_address(self, data):
return data['ipv6_address']['ref_title']
def convert_field_with_name_assigned_port(self,data):
return data['assigned_port']['title']
def convert_field_with_name_dns_domain(self, data):
rtn=[]
if 'dns_domain' in data and data['dns_domain'] is not None:
for ele in data['dns_domain']:
rtn.append(ele['title'])
return rtn

42
idoit_scaleup/cat_location.py Executable file
View File

@@ -0,0 +1,42 @@
from .consts import C__CATG__LOCATION
from .category import IDoitCategory
from pprint import pprint
from copy import deepcopy
class IDoitLocation(IDoitCategory):
CATEGORY = C__CATG__LOCATION
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_pos(self, data):
return int(data['pos']['visually_from'])
def convert_field_with_name_latitude(self, data):
if data['latitude'] == '':
return None
return float(data['latitude'])
def convert_field_with_name_longitude(self, data):
if data['longitude'] == '':
return None
return float(data['longitude'])
def fix_empty_position(self, data):
for pos_key in ['latitude', 'longitude']:
if not (pos_key in data):
data[pos_key] = None
elif data[pos_key] == '':
data[pos_key] = None
def save_category(self, objId, data):
cdata = deepcopy(data)
self.fix_empty_position(cdata)
return super().save_category(objId, cdata)
def update_category(self, objId, data):
cdata = deepcopy(data)
self.fix_empty_position(cdata)
return super().update_category(objId, cdata)

13
idoit_scaleup/cat_memory.py Executable file
View File

@@ -0,0 +1,13 @@
from .consts import C__CATG__MEMORY
from .category import IDoitCategory
class IDoitMemory(IDoitCategory):
CATEGORY = C__CATG__MEMORY
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_capacity(self, data):
return float(data['capacity']['title'])

40
idoit_scaleup/cat_network.py Executable file
View File

@@ -0,0 +1,40 @@
from .consts import C__CATS__NET
from .category import IDoitCategory
from pprint import pprint
from copy import deepcopy
from ipaddress import IPv4Network
from ipaddress import IPv6Network
class IDoitNetwork(IDoitCategory):
CATEGORY = C__CATS__NET
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_layer2_assignments(self, data):
rtn = []
for ele in data['layer2_assignments']:
rtn.append(int(ele['id']))
return rtn
def fix_mask_and_range(self, data):
net_str=f"{data['address']}/{data['cidr_suffix']}"
if int(data['type'])==1:
net= IPv4Network(net_str)
elif int(data['type'])==1000:
net= IPv6Network(net_str)
data['netmask']= str(net.netmask)
data['range_from'] = str(net[0])
data['range_to'] = str(net[-1])
def save_category(self, objId, data):
cdata = deepcopy(data)
self.fix_mask_and_range(cdata)
return super().save_category(objId, cdata)
def update_category(self, objId, data):
cdata = deepcopy(data)
self.fix_mask_and_range(cdata)
return super().update_category(objId, cdata)

View File

@@ -0,0 +1,64 @@
from .consts import C__CATG__NETWORK_LOG_PORT, C__CATG__IP, C__CATG__NETWORK_PORT
from .category import IDoitCategory
from copy import deepcopy
class IDoitNetworkLogicalPort(IDoitCategory):
CATEGORY = C__CATG__NETWORK_LOG_PORT
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_active(self, data):
return int(data['active']['value'])
def convert_field_with_name_interface(self, data):
if len(data['interface']) == 0:
return None
return int(data['interface'][0]['id'])
def convert_field_with_name_addresses(self, data):
return self.convert_list(data['addresses'])
def convert_field_with_name_layer2_assignment(self, data):
if data['layer2_assignment'] == []:
return None
# else:
raise Exception('unknown conversion ', data)
def convert_field_with_name_assigned_connector(self, data):
return self.conv_array_field('assigned_connector', data, 'ref_id')
def convert_field_with_name_net(self, data):
return self.convert_list(data['net'])
def save_category_if_changed(self, objId, data):
raise Exception(
'Funktioniert nur wenn es nur eine Kategorie gibt, ' +
'muss mit ID spezifiziert werden')
def fix_obj(self, cdata):
if ('interface' in cdata.keys()) and (cdata['interface'] is not None):
cdata['interface'] = "%d_C__CATG__NETWORK_INTERFACE" % cdata['interface']
if ('addresses' in cdata.keys()) and (cdata['addresses'] is not None):
rtn = []
for ele in cdata['addresses']:
rtn.append(str(ele))
cdata['addresses'] = rtn
if ('ports' in cdata.keys()) and (cdata['ports'] is not None):
rtn = []
for ele in cdata['ports']:
rtn.append("%d" % (ele))
cdata['ports'] = rtn
def save_category(self, objId, data):
cdata = deepcopy(data)
self.fix_obj(cdata)
return super().save_category(objId, cdata)
def update_category(self, objId, data):
cdata = deepcopy(data)
self.fix_obj(cdata)
return super().update_category(objId, cdata)

View File

@@ -0,0 +1,69 @@
from .consts import C__CATG__NETWORK_PORT
from .category import IDoitCategory
from copy import deepcopy
class IDoitNetworkPort(IDoitCategory):
CATEGORY = C__CATG__NETWORK_PORT
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_active(self, data):
return int(data['active']['value'])
def convert_field_with_name_interface(self, data):
if len(data['interface']) == 0:
return None
return int(data['interface'][0]['id'])
def convert_field_with_name_speed(self, data):
return float(data['speed']['title'])
def convert_field_with_name_cable(self, data):
return self.conv_array_field('cable', data, 'id')
def convert_field_with_name_addresses(self, data):
return self.convert_list(data['addresses'])
def convert_field_with_name_layer2_assignment(self, data):
if data['layer2_assignment'] == []:
return None
# else:
raise Exception('unknown conversion ', data)
def convert_field_with_name_assigned_connector(self, data):
return self.conv_array_field('assigned_connector', data, 'ref_id')
def convert_field_with_name_relation_direction(self, data):
return int(data['relation_direction']['id'])
def save_category_if_changed(self, objId, data):
raise Exception(
'Funktioniert nur wenn es nur eine Kategorie gibt, ' +
'muss mit ID spezifiziert werden')
def fix_obj(self, cdata):
#if ('interface' in cdata.keys()) and (cdata['interface'] is not None):
# cdata['interface'] = "%d_C__CATG__NETWORK_INTERFACE" % cdata['interface']
if ('addresses' in cdata.keys()) :
if cdata['addresses'] is None:
cdata['addresses'] = None
# FIXME Das geht im Moment nicht. siehe Idoit Bug #20429 (sanders)
else:
rtn = []
for ele in cdata['addresses']:
rtn.append(str(ele))
cdata['addresses'] = rtn
def save_category(self, objId, data):
cdata = deepcopy(data)
self.fix_obj(cdata)
return super().save_category(objId, cdata)
def update_category(self, objId, data):
cdata = deepcopy(data)
self.fix_obj(cdata)
return super().update_category(objId, cdata)

View File

@@ -0,0 +1,13 @@
from .consts import C__CATG__POWER_CONSUMER
from .category import IDoitCategory
class IDoitPowerConsumer(IDoitCategory):
CATEGORY = C__CATG__POWER_CONSUMER
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_active(self, data):
return int(data['active']['value'])

62
idoit_scaleup/cat_racktables.py Executable file
View File

@@ -0,0 +1,62 @@
from .consts import C__CATG__CUSTOM_FIELDS_RACKTABLES
from pprint import pprint
from .category import IDoitCategory
class Racktables(IDoitCategory):
CATEGORY = C__CATG__CUSTOM_FIELDS_RACKTABLES
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
self.rt_link = ''
self.rt_id = ''
self.rt_type = ''
self.rt_content = ''
for field in self.fields:
title = self.fields[field]['title']
if title == 'Racktables URL':
self.rt_link = field
if title == 'Racktables ID':
self.rt_id = field
if title == 'Racktables Object Type':
self.rt_type = field
if title == 'Racktables Inhalt':
self.rt_content = field
if ((self.rt_link == '') or
(self.rt_id == '') or
(self.rt_type == '') or
(self.rt_content == '')):
raise Exception('Object nicht deifinert')
def save_category(self, objId, data):
mydata = {}
if 'id' in data.keys():
mydata[self.rt_id] = data['id']
if 'link' in data.keys():
mydata[self.rt_link] = data['link']
if 'type' in data.keys():
mydata[self.rt_type] = data['type']
if 'content' in data.keys():
mydata[self.rt_content] = data['content']
if 'description' in data.keys():
mydata['description'] = data['description']
return super().save_category(objId, mydata)
def convert_incomming_category(self, data):
rtn = {}
if self.rt_id in data.keys():
rtn['id'] = data[self.rt_id]
if self.rt_link in data.keys():
rtn['link'] = data[self.rt_link]
if self.rt_type in data.keys():
rtn['type'] = data[self.rt_type]
if self.rt_content in data.keys():
rtn['content'] = data[self.rt_content]
if 'description' in data.keys():
rtn['description'] = data['description']
rtn['_data'] = data
return rtn

View File

@@ -0,0 +1,16 @@
from .consts import C__CATG__STORAGE_DEVICE
from .category import IDoitCategory
class IDoitStorageDevice(IDoitCategory):
CATEGORY = C__CATG__STORAGE_DEVICE
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_capacity(self, data):
return float(data['capacity']['title'])
def convert_field_with_name_hotspare(self, data):
return int(data['hotspare']['value'])

20
idoit_scaleup/cat_vlan.py Executable file
View File

@@ -0,0 +1,20 @@
from .consts import C__CATS__LAYER2_NET
from .category import IDoitCategory
from pprint import pprint
class IDoitVlan(IDoitCategory):
CATEGORY = C__CATS__LAYER2_NET
def __init__(self, cfg):
super().__init__(cfg, self.CATEGORY)
def convert_field_with_name_standard(self, data):
return int(data['standard']['value'])
def convert_field_with_name_layer3_assignments(self, data):
rtn = []
for ele in data['layer3_assignments']:
rtn.append(int(ele['id']))
return rtn

252
idoit_scaleup/category.py Executable file
View File

@@ -0,0 +1,252 @@
from pprint import pprint
from .base import IDoitApiBase
from copy import deepcopy
import json
class IDoitCategory(IDoitApiBase):
def __init__(self, cfg, obj_type: str):
super().__init__(cfg)
self.obj_type = obj_type
params = {
'category': obj_type
}
r = self.xml_rpc_call('cmdb.category_info', params)
self.fields = {}
for fieldname in r['result'].keys():
default = None
if 'default' in r['result'][fieldname]['ui']:
default = r['result'][fieldname]['ui']['default'] or None
self.fields[fieldname] = {
'data_type': r['result'][fieldname]['data']['type'],
'info_type': r['result'][fieldname]['info']['type'],
'ui_type': r['result'][fieldname]['ui']['type'],
'default': default,
'title': r['result'][fieldname]['info']['title']
}
def is_dialog_plus_field(self, fieldname):
return (self.fields[fieldname]['info_type'] == 'dialog_plus')
def save_category(self, objId, data):
sdata = deepcopy(data)
if "_data" in sdata.keys():
del (sdata["_data"])
params = {
"object": objId,
'category': self.obj_type,
'data': sdata}
if self.debug:
print('--Category Save---')
pprint(params)
print('--Category Save---')
return self.xml_rpc_call('cmdb.category.save', params)
def update_category(self, objId, data):
sdata = deepcopy(data)
if "_data" in sdata.keys():
del (sdata["_data"])
if "id" in sdata.keys():
sdata['category_id'] = sdata['id']
del (sdata["id"])
if sdata['category_id'] is None:
raise Exception('category_id is None')
params = {
"objID": objId,
'category': self.obj_type,
'data': sdata}
if self.debug:
print('--Category Update---')
pprint(params)
print('--Category Update---')
return self.xml_rpc_call('cmdb.category.update', params)
def read_categories(self, objId):
params = {
"objID": objId,
'category': self.obj_type,
}
r = self.xml_rpc_call('cmdb.category.read', params)
rtn = []
for item in r['result']:
rtn.append(self.convert_incomming_category(item))
return rtn
def read_category_by_id(self, objId, id):
for cat in self.read_categories(objId):
if cat['id'] == id:
return cat
# not found
return None
def delete_category(self, objId, id):
params = {
"objID": objId,
'category': self.obj_type,
'cateID': id
}
return self.xml_rpc_call('cmdb.category.delete', params)
def read_category(self, objId):
r = self.read_categories(objId)
if len(r) == 0:
return None
assert (len(r) == 1)
return r[0]
def conv_array_field(self, fieldname, data, ref_field):
if len(data[fieldname]) == 0:
return None
if type(data[fieldname]) is dict:
return int(data[fieldname][ref_field])
if len(data[fieldname]) != 1:
raise Exception('Field "%s" has more than one entry %s' %
(fieldname, json.dumps(data)))
return int(data[fieldname][0][ref_field])
def convert_list(self, list):
rtn = []
for ele in list:
rtn.append(int(ele['id']))
if len(rtn) == 0:
return None
return rtn
def convert_field(self, fieldname, data):
object_methods = [method_name for method_name in dir(self)
if callable(getattr(self, method_name))]
field = self.fields[fieldname]
if fieldname in data.keys():
if data[fieldname] is None:
return None
field_method_name = 'convert_field_with_name_%s' % fieldname
if field_method_name in object_methods:
method = getattr(self, field_method_name)
return method(data)
try:
if field['ui_type'] == 'popup':
if field['data_type'] == 'int':
return int(data[fieldname]['id'])
if field['ui_type'] == 'text':
if field['data_type'] == 'int':
return int(data[fieldname])
if field['data_type'] == 'double':
return float(data[fieldname])
if field['data_type'] == 'float':
return float(data[fieldname])
if field['data_type'] == 'link':
return data[fieldname]
if field['data_type'] == 'text':
return data[fieldname]
if field['ui_type'] == 'wysiwyg':
if field['data_type'] == 'text':
return data[fieldname]
if field['ui_type'] == 'textarea':
if field['data_type'] == 'text_area':
return data[fieldname]
if field['ui_type'] == 'dialog':
if field['data_type'] == 'int':
return int(data[fieldname]['id'])
if field['data_type'] == 'text':
return data[fieldname]['id']
if field['ui_type'] == 'f_dialog_list':
if field['data_type'] == 'int':
return self.convert_list(data[fieldname])
if field['ui_type'] == 'datetime':
if field['data_type'] == 'date_time':
try:
rtn=data[fieldname]['title']
except:
rtn=data[fieldname]
return rtn
if field['ui_type'] == 'numeric':
if field['data_type'] == 'text':
return float(data[fieldname])
except:
raise Exception('Wrong conversion ',
self.obj_type, fieldname, field, data)
raise Exception('Unknwown data_type/ ui_type',
self.obj_type, fieldname, field, data)
def convert_incomming_category(self, data):
rtn = {}
for fieldname in self.fields.keys():
rtn[fieldname] = self.convert_field(fieldname, data)
if 'id' in data.keys():
rtn['id'] = int(data['id'])
rtn['_data'] = data
return rtn
def partial_equal(self, obj1, obj2):
if isinstance(obj1, str):
return (obj1 == obj2)
if isinstance(obj1, int):
return (obj1 == obj2)
if obj1 is None and obj2 is None:
return True
if obj1 is None:
return False
if obj2 is None:
return False
if isinstance(obj1, list):
if isinstance(obj2, list):
if len(obj1) != len(obj2):
return False
for ele in obj1:
if ele not in obj2:
return False
return True
else:
return False
for key in obj1.keys():
if key not in obj2:
return False
if not (self.partial_equal(obj1[key], obj2[key])):
return False
return True
# Funktioniert nur wo es genau eine Kategory gibt
def save_category_if_changed(self, objId, data):
oldData = self.read_category(objId)
if not (self.partial_equal(data, oldData)):
print('save', objId, self.obj_type)
pprint(data)
print('old:')
pprint(oldData)
r = self.save_category(objId, data)
print(r)
def update_categorys(self, objId, equals_attr, new_data_arr):
old_data_arr = self.read_categories(objId)
for old_data in old_data_arr:
old_found = False
for new_data in new_data_arr:
if old_data[equals_attr] == new_data[equals_attr]:
old_found = True
if not (self.partial_equal(new_data, old_data)):
print('save', objId, self.obj_type)
pprint(new_data)
print('old:')
pprint(old_data)
new_data['id'] = old_data['id']
r = self.update_category(objId, new_data)
pprint(r)
if not old_found:
print('delete:', objId, self.obj_type)
pprint(old_data)
self.delete_category(objId, old_data['id'])
for new_data in new_data_arr:
new_found = False
for old_data in old_data_arr:
if old_data[equals_attr] == new_data[equals_attr]:
new_found = True
if not new_found:
print('save', objId, self.obj_type)
pprint(new_data)
r = self.save_category(objId, new_data)
pprint(r)

View File

@@ -0,0 +1,29 @@
from pprint import pprint
from .base import IDoitApiBase
class IDoitConditionalRead(IDoitApiBase):
def __init__(self, cfg):
super().__init__(cfg)
self.clear_search_list()
def clear_search_list(self):
self.search_list = []
def add_search_param(self, category: str, field: str, value: str, operator: str = None, compare: str = "=", ):
entry = {
'property': "%s-%s" % (category, field),
'comparison': compare,
'value': value,
}
if operator:
entry['operator'] = operator
self.search_list.append(entry)
def search(self):
params = {
'conditions': self.search_list,
}
rtn = self.xml_rpc_call('cmdb.condition.read', params)
return rtn['result']

38
idoit_scaleup/consts.py Executable file
View File

@@ -0,0 +1,38 @@
C__CATG__ACCESS = 'C__CATG__ACCESS'
C__CATG__APPLICATION = 'C__CATG__APPLICATION'
C__CATG__ADDRESS = 'C__CATG__ADDRESS'
C__CATG__CONNECTOR = 'C__CATG__CONNECTOR'
C__CATG__CPU = 'C__CATG__CPU'
#C__CATG__CUSTOM_FIELDS_RACKTABLES = 'C__CATG__CUSTOM_FIELDS_RACKTABLES'
C__CATG__FORMFACTOR = 'C__CATG__FORMFACTOR'
C__CATG__IDENTIFIER = 'C__CATG__IDENTIFIER'
C__CATG__IP = 'C__CATG__IP'
C__CATG__LOCATION = 'C__CATG__LOCATION'
C__CATG__MEMORY = 'C__CATG__MEMORY'
C__CATG__MODEL = 'C__CATG__MODEL'
C__CATG__NETWORK_LOG_PORT = 'C__CATG__NETWORK_LOG_PORT'
C__CATG__NETWORK_PORT = 'C__CATG__NETWORK_PORT'
C__CATG__POWER_CONSUMER = 'C__CATG__POWER_CONSUMER'
C__CATG__STORAGE_DEVICE = 'C__CATG__STORAGE_DEVICE'
C__CATS__ENCLOSURE = 'C__CATS__ENCLOSURE'
C__CATS__LAYER2_NET = 'C__CATS__LAYER2_NET'
C__CATS__NET = 'C__CATS__NET'
C__CATS__PERSON_MASTER = 'C__CATS__PERSON_MASTER'
C__OBJTYPE__BUILDING = 'C__OBJTYPE__BUILDING'
C__OBJTYPE__CABLE = 'C__OBJTYPE__CABLE'
C__OBJTYPE__CITY = 'C__OBJTYPE__CITY'
C__OBJTYPE__COUNTRY = 'C__OBJTYPE__COUNTRY'
C__OBJTYPE__ENCLOSURE = 'C__OBJTYPE__ENCLOSURE'
C__OBJTYPE__LAYER2_NET = 'C__OBJTYPE__LAYER2_NET'
C__OBJTYPE__LAYER3_NET = 'C__OBJTYPE__LAYER3_NET'
C__OBJTYPE__PATCH_PANEL = 'C__OBJTYPE__PATCH_PANEL'
C__OBJTYPE__PDU = 'C__OBJTYPE__PDU'
C__OBJTYPE__RACK_SEGMENT = 'C__OBJTYPE__RACK_SEGMENT'
C__OBJTYPE__ROOM = 'C__OBJTYPE__ROOM'
C__OBJTYPE__ROOM = 'C__OBJTYPE__ROOM'
C__OBJTYPE__SERVER = 'C__OBJTYPE__SERVER'
C__OBJTYPE__SWITCH = 'C__OBJTYPE__SWITCH'
C__OBJTYPE__WIRING_SYSTEM = 'C__OBJTYPE__WIRING_SYSTEM'
C__OBJTYPE__WHMCS_CUSTOMER = 'C__OBJTYPE__WHMCS_CUSTOMER'

67
idoit_scaleup/dialog.py Executable file
View File

@@ -0,0 +1,67 @@
from .base import IDoitApiBase
class IDoitDialog(IDoitApiBase):
def __init__(self, cfg, obj_type: str, property: str):
super().__init__(cfg)
self.obj_type = obj_type
self.property = property
self.cache = {}
def get_all(self):
if self.cache == {}:
params = {
'category': self.obj_type,
'property': self.property
}
r = self.xml_rpc_call('cmdb.dialog.read', params)
# Workaround für Ticket #22087
# https://help.i-doit.com/hc/en-us/requests/22087
if len(r['result'])==1:
if isinstance(r['result'][0],list):
r['result']=r['result'][0]
self.cache = r
else:
r = self.cache
return self.cache['result']
def get(self, value: str, parent: int = None):
for entry in self.get_all():
if parent is None:
if value == entry['title']:
return int(entry['id'])
else:
if (value == entry['title'] and
entry['parent']['id'] == str(parent)):
return int(entry['id'])
return None
def get_ignore_case(self, value: str, parent: int = None):
for entry in self.get_all():
title=entry['title'].lower()
if parent is None:
if value.lower() == title:
return int(entry['id'])
else:
if (value.lower() == title and
entry['parent']['id'] == str(parent)):
return int(entry['id'])
return None
def create(self, value: str, parent: int = None):
params = {
'category': self.obj_type,
'property': self.property,
'value': value
}
self.cache = {}
if parent is not None:
params['parent'] = parent
r = self.xml_rpc_call('cmdb.dialog.create', params)
return r['result']['entry_id']
def create_or_get_id(self, value: str, parent: int = None):
id = self.get(value, parent)
if id is None:
id = self.create(value, parent)
return id

98
idoit_scaleup/object.py Executable file
View File

@@ -0,0 +1,98 @@
from typing import List
from .base import IDoitApiBase
class IDoitObject(IDoitApiBase):
def __init__(self, cfg, obj_type: str):
super().__init__(cfg)
self.obj_type = obj_type
def get_by_title(self, title: str, categories: List = []):
params = {
'filter': {
'type': self.obj_type,
'title': title,
},
}
if len(categories) > 0:
params['categories'] = categories
rtn = self.xml_rpc_call('cmdb.objects', params)
if len(rtn['result']) == 0:
return None
else:
return rtn['result'][0]
def get_by_id(self, obj_id: str, categories: List = []):
params = {
'id': obj_id
}
if len(categories) > 0:
params['categories'] = categories
rtn = self.xml_rpc_call('cmdb.object', params)
return rtn['result']
def get_all(self, categories: List = [], ids = None):
params = {
'filter': {
'type': self.obj_type
},
}
if ids:
params['filter']['ids'] = ids
if len(categories) > 0:
params['categories'] = categories
rtn = self.xml_rpc_call('cmdb.objects', params)
return rtn['result']
def create_object_with_title(self, title: str):
params = {
'title': title,
'type': self.obj_type
}
return self.xml_rpc_call('cmdb.object.create', params)
def create_object_if_not_there(self, title):
obj = self.get_by_title(title)
if obj is None:
r = self.create_object_with_title(title)
print('-------------------')
print("%s (%s) " % (title, self.obj_type))
print('-------------------')
objId = r['result']['id']
else:
objId = obj['id']
return objId
def update_object(self, obj_id: str, title: str):
params = {
'id': obj_id,
'title': title,
}
return self.xml_rpc_call('cmdb.object.update', params)
def archive_object(self, obj_id: str):
params = {
'id': obj_id,
'status': 'C__RECORD_STATUS__ARCHIVED',
}
return self.xml_rpc_call('cmdb.object.delete', params)
def delete_object(self, obj_id: str):
params = {
'id': obj_id,
'status': 'C__RECORD_STATUS__DELETED',
}
return self.xml_rpc_call('cmdb.object.delete', params)
def purge_object(self, obj_id: str):
params = {
'id': obj_id,
'status': 'C__RECORD_STATUS__PURGE',
}
return self.xml_rpc_call('cmdb.object.delete', params)
def recycle_object(self, obj_id: str):
params = {
'id': obj_id,
}
return self.xml_rpc_call('cmdb.object.recycle', params)

12
idoit_scaleup/search.py Executable file
View File

@@ -0,0 +1,12 @@
from pprint import pprint
from .base import IDoitApiBase
class IDoitSearch(IDoitApiBase):
def search(self, search: str):
params = {
'q': search,
}
rtn = self.xml_rpc_call('idoit.search', params)
return rtn['result']