ipfabric_netbox 4.3.2__py3-none-any.whl → 4.3.2b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ipfabric_netbox might be problematic. Click here for more details.
- ipfabric_netbox/__init__.py +1 -1
- ipfabric_netbox/data/transform_map.json +11 -11
- ipfabric_netbox/exceptions.py +3 -38
- ipfabric_netbox/migrations/0021_update_transform_maps.py +133 -0
- ipfabric_netbox/models.py +36 -17
- ipfabric_netbox/signals.py +14 -26
- ipfabric_netbox/templates/ipfabric_netbox/ipfabricingestion.html +2 -2
- ipfabric_netbox/tests/test_models.py +24 -19
- ipfabric_netbox/utilities/ipfutils.py +634 -513
- ipfabric_netbox/utilities/transform_map.py +173 -0
- {ipfabric_netbox-4.3.2.dist-info → ipfabric_netbox-4.3.2b2.dist-info}/METADATA +2 -1
- {ipfabric_netbox-4.3.2.dist-info → ipfabric_netbox-4.3.2b2.dist-info}/RECORD +13 -13
- ipfabric_netbox/utilities/nbutils.py +0 -79
- {ipfabric_netbox-4.3.2.dist-info → ipfabric_netbox-4.3.2b2.dist-info}/WHEEL +0 -0
|
@@ -3,6 +3,8 @@ import json
|
|
|
3
3
|
|
|
4
4
|
from django.apps import apps as django_apps
|
|
5
5
|
|
|
6
|
+
# region Transform Map Creation
|
|
7
|
+
|
|
6
8
|
# These functions are used in the migration file to prepare the transform maps
|
|
7
9
|
# Because of this we have to use historical models
|
|
8
10
|
# see https://docs.djangoproject.com/en/5.1/topics/migrations/#historical-models
|
|
@@ -58,3 +60,174 @@ def get_transform_map() -> dict:
|
|
|
58
60
|
with open(data_file, "rb") as data_file:
|
|
59
61
|
return json.load(data_file)
|
|
60
62
|
raise FileNotFoundError("'transform_map.json' not found in installed package")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# endregion
|
|
66
|
+
# region Transform Map Updating
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class Record:
|
|
70
|
+
"""Base class for field and relationship records."""
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
coalesce: bool | None = None,
|
|
75
|
+
old_template: str = None,
|
|
76
|
+
new_template: str = None,
|
|
77
|
+
):
|
|
78
|
+
self.coalesce = coalesce
|
|
79
|
+
# Keep the original template here rather than loading it from transform_map.json
|
|
80
|
+
# so our revert won’t break if that template ever changes.
|
|
81
|
+
self.old_template = old_template
|
|
82
|
+
self.new_template = new_template
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class FieldRecord(Record):
|
|
86
|
+
def __init__(
|
|
87
|
+
self,
|
|
88
|
+
source_field: str,
|
|
89
|
+
target_field: str,
|
|
90
|
+
new_source_field: str | None = None,
|
|
91
|
+
new_target_field: str | None = None,
|
|
92
|
+
**kwargs,
|
|
93
|
+
):
|
|
94
|
+
super().__init__(**kwargs)
|
|
95
|
+
self.source_field = source_field
|
|
96
|
+
self.target_field = target_field
|
|
97
|
+
self.new_source_field = new_source_field
|
|
98
|
+
self.new_target_field = new_target_field
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class RelationshipRecord(Record):
|
|
102
|
+
def __init__(self, source_model: str, target_field: str, **kwargs):
|
|
103
|
+
super().__init__(**kwargs)
|
|
104
|
+
self.source_model = source_model
|
|
105
|
+
self.target_field = target_field
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class TransformMapRecord:
|
|
109
|
+
def __init__(
|
|
110
|
+
self,
|
|
111
|
+
source_model: str,
|
|
112
|
+
target_model: str,
|
|
113
|
+
fields: tuple[FieldRecord, ...] = tuple(),
|
|
114
|
+
relationships: tuple[RelationshipRecord, ...] = tuple(),
|
|
115
|
+
):
|
|
116
|
+
self.source_model = source_model
|
|
117
|
+
self.target_model = target_model
|
|
118
|
+
self.fields = fields
|
|
119
|
+
self.relationships = relationships
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def do_change(
|
|
123
|
+
apps, schema_editor, changes: tuple[TransformMapRecord, ...], forward: bool = True
|
|
124
|
+
):
|
|
125
|
+
"""Apply the changes, `forward` determines direction."""
|
|
126
|
+
|
|
127
|
+
ContentType = apps.get_model("contenttypes", "ContentType")
|
|
128
|
+
IPFabricTransformMap = apps.get_model("ipfabric_netbox", "IPFabricTransformMap")
|
|
129
|
+
IPFabricTransformField = apps.get_model("ipfabric_netbox", "IPFabricTransformField")
|
|
130
|
+
IPFabricRelationshipField = apps.get_model(
|
|
131
|
+
"ipfabric_netbox", "IPFabricRelationshipField"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
for change in changes:
|
|
136
|
+
app, model = change.target_model.split(".")
|
|
137
|
+
try:
|
|
138
|
+
transform_map = IPFabricTransformMap.objects.get(
|
|
139
|
+
source_model=change.source_model,
|
|
140
|
+
target_model=ContentType.objects.get(app_label=app, model=model),
|
|
141
|
+
)
|
|
142
|
+
except IPFabricTransformMap.DoesNotExist:
|
|
143
|
+
continue
|
|
144
|
+
|
|
145
|
+
for field in change.fields:
|
|
146
|
+
# Find the correct transform field.
|
|
147
|
+
# Only 1 should be found if it exists, but keep it as queryset so we can filter and update.
|
|
148
|
+
transform_field_qs = IPFabricTransformField.objects.filter(
|
|
149
|
+
transform_map=transform_map,
|
|
150
|
+
source_field=field.source_field
|
|
151
|
+
if forward
|
|
152
|
+
else field.new_source_field or field.source_field,
|
|
153
|
+
target_field=field.target_field
|
|
154
|
+
if forward
|
|
155
|
+
else field.new_target_field or field.target_field,
|
|
156
|
+
)
|
|
157
|
+
if not transform_field_qs.exists():
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
if field.old_template is not None and field.new_template is not None:
|
|
161
|
+
# First update the template if needed
|
|
162
|
+
transform_field_qs.filter(
|
|
163
|
+
template=field.old_template if forward else field.new_template
|
|
164
|
+
).update(
|
|
165
|
+
template=field.new_template if forward else field.old_template
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
if field.coalesce is not None:
|
|
169
|
+
# Next update coalesce if needed
|
|
170
|
+
transform_field_qs.filter(
|
|
171
|
+
coalesce=not field.coalesce if forward else field.coalesce
|
|
172
|
+
).update(coalesce=field.coalesce if forward else not field.coalesce)
|
|
173
|
+
|
|
174
|
+
if (
|
|
175
|
+
field.new_target_field is not None
|
|
176
|
+
or field.new_source_field is not None
|
|
177
|
+
):
|
|
178
|
+
# And at the end update source_field/target_field if needed
|
|
179
|
+
transform_field_qs.update(
|
|
180
|
+
source_field=field.new_source_field or field.source_field
|
|
181
|
+
if forward
|
|
182
|
+
else field.source_field,
|
|
183
|
+
target_field=field.new_target_field or field.target_field
|
|
184
|
+
if forward
|
|
185
|
+
else field.target_field,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
for relationship in change.relationships:
|
|
189
|
+
s_app, s_model = relationship.source_model.split(".")
|
|
190
|
+
source_model = ContentType.objects.get(app_label=s_app, model=s_model)
|
|
191
|
+
|
|
192
|
+
# Find the correct relationship field.
|
|
193
|
+
# Only 1 should be found if it exists, but keep it as queryset so we can filter and update.
|
|
194
|
+
relationship_qs = IPFabricRelationshipField.objects.filter(
|
|
195
|
+
transform_map=transform_map,
|
|
196
|
+
source_model=source_model,
|
|
197
|
+
target_field=relationship.target_field,
|
|
198
|
+
)
|
|
199
|
+
if not relationship_qs.exists():
|
|
200
|
+
continue
|
|
201
|
+
|
|
202
|
+
if (
|
|
203
|
+
relationship.old_template is not None
|
|
204
|
+
and relationship.new_template is not None
|
|
205
|
+
):
|
|
206
|
+
# First update the template if needed
|
|
207
|
+
relationship_qs.filter(
|
|
208
|
+
template=relationship.old_template
|
|
209
|
+
if forward
|
|
210
|
+
else relationship.new_template,
|
|
211
|
+
).update(
|
|
212
|
+
template=relationship.new_template
|
|
213
|
+
if forward
|
|
214
|
+
else relationship.old_template
|
|
215
|
+
),
|
|
216
|
+
|
|
217
|
+
if relationship.coalesce is not None:
|
|
218
|
+
# Next update coalesce if needed
|
|
219
|
+
relationship_qs.filter(
|
|
220
|
+
coalesce=not relationship.coalesce
|
|
221
|
+
if forward
|
|
222
|
+
else relationship.coalesce,
|
|
223
|
+
).update(
|
|
224
|
+
coalesce=relationship.coalesce
|
|
225
|
+
if forward
|
|
226
|
+
else not relationship.coalesce
|
|
227
|
+
),
|
|
228
|
+
|
|
229
|
+
except Exception as e:
|
|
230
|
+
print(f"Error applying Transform map updates: {e}")
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ipfabric_netbox
|
|
3
|
-
Version: 4.3.
|
|
3
|
+
Version: 4.3.2b2
|
|
4
4
|
Summary: NetBox plugin to sync IP Fabric data into NetBox
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: netbox,ipfabric,plugin,sync
|
|
@@ -19,6 +19,7 @@ Provides-Extra: ipfabric-6-10
|
|
|
19
19
|
Provides-Extra: ipfabric-7-0
|
|
20
20
|
Provides-Extra: ipfabric-7-2
|
|
21
21
|
Provides-Extra: ipfabric-7-3
|
|
22
|
+
Requires-Dist: httpx (>0.26,<0.29)
|
|
22
23
|
Requires-Dist: ipfabric (>=6.10.0,<6.11.0) ; extra == "ipfabric_6_10" and extra != "ipfabric_7_0" and extra != "ipfabric_7_2" and extra != "ipfabric_7_3"
|
|
23
24
|
Requires-Dist: ipfabric (>=6.6.4) ; extra != "ipfabric_6_10" and extra != "ipfabric_7_0" and extra != "ipfabric_7_2" and extra != "ipfabric_7_3"
|
|
24
25
|
Requires-Dist: ipfabric (>=7.0.0,<7.1.0) ; extra != "ipfabric_6_10" and extra == "ipfabric_7_0" and extra != "ipfabric_7_2" and extra != "ipfabric_7_3"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
ipfabric_netbox/__init__.py,sha256
|
|
1
|
+
ipfabric_netbox/__init__.py,sha256=pEVJZiXGhR0CBOp0KyoC8ufk1zjiu4iwim4aiM4aq1A,674
|
|
2
2
|
ipfabric_netbox/api/__init__.py,sha256=XRclTGWVR0ZhAAwgYul5Wm_loug5_hUjEumbLQEwKYM,47
|
|
3
3
|
ipfabric_netbox/api/serializers.py,sha256=92Cwhnqsm1l1oZfdHH5aJI1VFX0eO5JS4BsdXE6Ur18,6738
|
|
4
4
|
ipfabric_netbox/api/urls.py,sha256=1fXXVTxNY5E64Nfz6b7zXD9bZI3FcefuxAWKMe0w_QU,1240
|
|
5
5
|
ipfabric_netbox/api/views.py,sha256=qOBTIzPtOBY75tTjirsTBbiRXrQQid478Tp15-WKbmQ,6859
|
|
6
6
|
ipfabric_netbox/choices.py,sha256=r1A7zasYw92fdB6MxnvcLkzz4mA61_wSUmbfuDbmg0M,6017
|
|
7
|
-
ipfabric_netbox/data/transform_map.json,sha256=
|
|
8
|
-
ipfabric_netbox/exceptions.py,sha256=
|
|
7
|
+
ipfabric_netbox/data/transform_map.json,sha256=dYPXiaLJFuO9vabGgkuywn7XFCe7xdgPrfvOvP206TM,22016
|
|
8
|
+
ipfabric_netbox/exceptions.py,sha256=5nyAVoaPEGDHcrUXNpsCr_Nhq1vz1VbAmq54fU03iRg,1453
|
|
9
9
|
ipfabric_netbox/filtersets.py,sha256=4I_ogO0Wqexf4e4gy_CirdGmA6vSCybyCadFcjI2LM8,8011
|
|
10
10
|
ipfabric_netbox/forms.py,sha256=s9jYgK75CJzCrhnEeB3WxxZ9bF2YfNDA4N-sO9xTqgc,50068
|
|
11
11
|
ipfabric_netbox/graphql/__init__.py,sha256=-a5w_VY7pc-RVt8MvThkTzeAqCC3xCan4Ue6iMefmjI,754
|
|
@@ -35,10 +35,11 @@ ipfabric_netbox/migrations/0017_ipfabricsync_update_custom_fields.py,sha256=IVbA
|
|
|
35
35
|
ipfabric_netbox/migrations/0018_remove_type_field.py,sha256=ffxW6IS3BLCbvM5M9DbDb_x6spMmRxnV1iq8IuXxMGw,385
|
|
36
36
|
ipfabric_netbox/migrations/0019_alter_ipfabrictransformmap_options_and_more.py,sha256=ieDVedt9KpJBicAiC3kdZXzHeos12N0L9EdRXKmIVgY,501
|
|
37
37
|
ipfabric_netbox/migrations/0020_clean_scheduled_jobs.py,sha256=zjCVKnCWTKYYkpVRwHjqRIRR2j6ALSKXYMfraRjNu7Y,2652
|
|
38
|
+
ipfabric_netbox/migrations/0021_update_transform_maps.py,sha256=W9GSgMQNmEdxnRI1c13at3XG1F_hyo9oZWsTZ0TLN9c,5464
|
|
38
39
|
ipfabric_netbox/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
ipfabric_netbox/models.py,sha256=
|
|
40
|
+
ipfabric_netbox/models.py,sha256=5bgQzfGfCUWQdRL3j6CNFXVDW3oDfxpQ0Y6JCKRJz-M,39250
|
|
40
41
|
ipfabric_netbox/navigation.py,sha256=g2PyyaMqjgYwO3VIKza8vMS-dhbkvxscsHwVfWBj_dk,2287
|
|
41
|
-
ipfabric_netbox/signals.py,sha256=
|
|
42
|
+
ipfabric_netbox/signals.py,sha256=y3x2jKT8yTjOfC4B3h4YZPRsYQkBal4cFdHJFkbPoS8,1411
|
|
42
43
|
ipfabric_netbox/tables.py,sha256=jXiHcRrR4XwkvyUnnU92JW290nZg-85IdpKjsQOsFcc,9052
|
|
43
44
|
ipfabric_netbox/template_content.py,sha256=lxZ02BFVihbSgjXCETGsWmhdElQUUO3uUGd0WfhlRmw,1120
|
|
44
45
|
ipfabric_netbox/templates/ipfabric_netbox/inc/clone_form.html,sha256=f6O5ugjQg7u37QWxUpKvE38jNslwb3rCMghlAUqjWBk,1127
|
|
@@ -52,7 +53,7 @@ ipfabric_netbox/templates/ipfabric_netbox/inc/snapshotdata.html,sha256=1ItOCPjjp
|
|
|
52
53
|
ipfabric_netbox/templates/ipfabric_netbox/inc/transform_map_field_map.html,sha256=MSpU2mQnrGg_jA1-eqQgaSK9DXCeo3w6j33tV_GFNJ4,535
|
|
53
54
|
ipfabric_netbox/templates/ipfabric_netbox/inc/transform_map_relationship_map.html,sha256=tmIV0gDhfVxBse4xDeE5atMi4KEMkvxB_WRx94gu44U,539
|
|
54
55
|
ipfabric_netbox/templates/ipfabric_netbox/ipfabric_table.html,sha256=HsxENF0KaaGT8w0_K6251LVH0W_mg60W8ktApxAG59U,1689
|
|
55
|
-
ipfabric_netbox/templates/ipfabric_netbox/ipfabricingestion.html,sha256=
|
|
56
|
+
ipfabric_netbox/templates/ipfabric_netbox/ipfabricingestion.html,sha256=4cUP5KxCEtH4j5RFT68-7UJUCnJcOCxA0iBzrxwua4I,4760
|
|
56
57
|
ipfabric_netbox/templates/ipfabric_netbox/ipfabricsnapshot.html,sha256=HWCGi1e0O_jL-5XnIYfCC5EQh5oSw-1-ZUpjH6-cGV0,3690
|
|
57
58
|
ipfabric_netbox/templates/ipfabric_netbox/ipfabricsource.html,sha256=I9K7Eob-jjNAy6lryq2QKpp-5JyR1DEJSPF3D6JKR_w,4063
|
|
58
59
|
ipfabric_netbox/templates/ipfabric_netbox/ipfabricsync.html,sha256=M7tig8Y42ndsipBHKVVfSFb9tSGvm7Cf4fj-B54xizs,4852
|
|
@@ -74,15 +75,14 @@ ipfabric_netbox/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
|
74
75
|
ipfabric_netbox/tests/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
76
|
ipfabric_netbox/tests/api/test_api.py,sha256=rnpGj3_cuh-QGQgOoARWuvtipDNCjcICn_Qbv2kUMQA,35304
|
|
76
77
|
ipfabric_netbox/tests/test_forms.py,sha256=ZZezIMjf5UiFGzpIlfIdnmXK5Urk8SdapF5c2MMOYoA,61693
|
|
77
|
-
ipfabric_netbox/tests/test_models.py,sha256=
|
|
78
|
+
ipfabric_netbox/tests/test_models.py,sha256=gagJKoxD-BnEMWwZ2d5uImrWJOqYgfXe23JRikcoruo,16420
|
|
78
79
|
ipfabric_netbox/tests/test_views.py,sha256=KKHKA4ejTEwdy6Ce5StJxjxWVWbQ54Y1puyPeBRw1vM,87923
|
|
79
80
|
ipfabric_netbox/urls.py,sha256=qF2BzZEDnPRd3opFaRfiMdaarYKFfv69iMaAbU2rsBU,2702
|
|
80
81
|
ipfabric_netbox/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
|
-
ipfabric_netbox/utilities/ipfutils.py,sha256=
|
|
82
|
+
ipfabric_netbox/utilities/ipfutils.py,sha256=wc6wVBEHKJ8RoCOrp6Fm3w08nf1xiHGGMsMYrypOcpA,38852
|
|
82
83
|
ipfabric_netbox/utilities/logging.py,sha256=GYknjocMN6LQ2873_az3y0RKm29TCXaWviUIIneH-x0,3445
|
|
83
|
-
ipfabric_netbox/utilities/
|
|
84
|
-
ipfabric_netbox/utilities/transform_map.py,sha256=GpM_7Mm6FE0qV2qbyj4YfDn0l-JkeeEHQOZkNVSSHk4,2391
|
|
84
|
+
ipfabric_netbox/utilities/transform_map.py,sha256=nJhEdi2DqqowrtfowNgg-FZiE3_lN0MhQvaNwHS4yXw,8979
|
|
85
85
|
ipfabric_netbox/views.py,sha256=CPVtPvHcKCeCAusxjC0WvnOUKn6p5m3lgd57wOp29dI,44829
|
|
86
|
-
ipfabric_netbox-4.3.
|
|
87
|
-
ipfabric_netbox-4.3.
|
|
88
|
-
ipfabric_netbox-4.3.
|
|
86
|
+
ipfabric_netbox-4.3.2b2.dist-info/METADATA,sha256=klFh0MZzp-7HtCQ-hZtJvqtg7cnZxMwIn8NztNE4JlA,4789
|
|
87
|
+
ipfabric_netbox-4.3.2b2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
88
|
+
ipfabric_netbox-4.3.2b2.dist-info/RECORD,,
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
from collections import Counter
|
|
2
|
-
from copy import deepcopy
|
|
3
|
-
|
|
4
|
-
from dcim.models import Device
|
|
5
|
-
from dcim.models import InventoryItem
|
|
6
|
-
from dcim.models import Manufacturer
|
|
7
|
-
|
|
8
|
-
DEFAULT_DEVICE_ROLE = "Network Device"
|
|
9
|
-
device_serial_max_length = Device._meta.get_field("serial").max_length
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def order_members(members):
|
|
13
|
-
devices = {}
|
|
14
|
-
|
|
15
|
-
for member in members:
|
|
16
|
-
master_serial = member.get("sn")
|
|
17
|
-
if master_serial and member.get("memberSn"):
|
|
18
|
-
if master_serial in devices:
|
|
19
|
-
devices[master_serial].append(member)
|
|
20
|
-
else:
|
|
21
|
-
devices[master_serial] = [member]
|
|
22
|
-
|
|
23
|
-
return devices
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def order_devices(devices, members):
|
|
27
|
-
hostnames = [d["hostname"] for d in devices]
|
|
28
|
-
counter = Counter(hostnames)
|
|
29
|
-
|
|
30
|
-
new_devices = []
|
|
31
|
-
|
|
32
|
-
for device in devices:
|
|
33
|
-
if counter[device["hostname"]] > 1:
|
|
34
|
-
device["hostname"] = f"{device['hostname']} - ({device['sn']})"
|
|
35
|
-
if child_members := members.get(device.get("sn")):
|
|
36
|
-
for child_member in child_members:
|
|
37
|
-
if device.get("sn") != child_member.get("memberSn"):
|
|
38
|
-
new_device = deepcopy(device)
|
|
39
|
-
new_device[
|
|
40
|
-
"hostname"
|
|
41
|
-
] = f"{device['hostname']}/{child_member.get('member')}"
|
|
42
|
-
new_device["model"] = child_member.get("pn")
|
|
43
|
-
new_device["sn"] = child_member.get("memberSn")
|
|
44
|
-
new_device["virtual_chassis"] = child_member
|
|
45
|
-
new_devices.append(new_device)
|
|
46
|
-
else:
|
|
47
|
-
device["virtual_chassis"] = child_member
|
|
48
|
-
hostnames = [d["hostname"] for d in devices]
|
|
49
|
-
counter = Counter(hostnames)
|
|
50
|
-
|
|
51
|
-
devices.extend(new_devices)
|
|
52
|
-
|
|
53
|
-
return devices
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def create_inventory_items(device: Device, parts: list, manufacturer: Manufacturer):
|
|
57
|
-
for part in parts:
|
|
58
|
-
name = part.get("name", "")
|
|
59
|
-
if len(name) > InventoryItem._meta.get_field("name").max_length:
|
|
60
|
-
if part.get("dscr"):
|
|
61
|
-
name = part.get("dscr")
|
|
62
|
-
else:
|
|
63
|
-
name = part.get("sn")
|
|
64
|
-
|
|
65
|
-
defaults = {
|
|
66
|
-
"name": name,
|
|
67
|
-
"manufacturer": manufacturer,
|
|
68
|
-
"serial": part.get("sn", ""),
|
|
69
|
-
# "description": part.get('dscr', "123"),
|
|
70
|
-
"part_id": part.get("pid", ""),
|
|
71
|
-
"device": device,
|
|
72
|
-
"lft": device.pk,
|
|
73
|
-
}
|
|
74
|
-
if part.get("dscr"):
|
|
75
|
-
defaults["description"] = part.get("dscr")
|
|
76
|
-
|
|
77
|
-
inventory_object, _ = InventoryItem.objects.update_or_create(
|
|
78
|
-
serial=part.get("sn", ""), defaults=defaults
|
|
79
|
-
)
|
|
File without changes
|