annet 2.5.3__tar.gz → 2.6.0__tar.gz

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 annet might be problematic. Click here for more details.

Files changed (208) hide show
  1. {annet-2.5.3/annet.egg-info → annet-2.6.0}/PKG-INFO +2 -2
  2. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/manufacturer.py +1 -0
  3. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/models.py +10 -2
  4. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/storage_base.py +1 -0
  5. {annet-2.5.3 → annet-2.6.0}/annet/annet.py +8 -1
  6. {annet-2.5.3 → annet-2.6.0}/annet/annlib/netdev/devdb/data/devdb.json +1 -0
  7. {annet-2.5.3 → annet-2.6.0}/annet/annlib/netdev/views/hardware.py +3 -0
  8. {annet-2.5.3 → annet-2.6.0}/annet/annlib/rbparser/platform.py +4 -0
  9. {annet-2.5.3 → annet-2.6.0}/annet/annlib/rulebook/common.py +1 -1
  10. {annet-2.5.3 → annet-2.6.0}/annet/generators/__init__.py +1 -1
  11. {annet-2.5.3 → annet-2.6.0}/annet/parallel.py +28 -9
  12. annet-2.6.0/annet/rulebook/texts/arista.rul +82 -0
  13. annet-2.6.0/annet/rulebook/texts/iosxr.deploy +27 -0
  14. annet-2.6.0/annet/rulebook/texts/iosxr.order +85 -0
  15. annet-2.6.0/annet/rulebook/texts/iosxr.rul +110 -0
  16. {annet-2.5.3 → annet-2.6.0}/annet/tabparser.py +1 -1
  17. {annet-2.5.3 → annet-2.6.0/annet.egg-info}/PKG-INFO +2 -2
  18. {annet-2.5.3 → annet-2.6.0}/annet.egg-info/SOURCES.txt +3 -0
  19. {annet-2.5.3 → annet-2.6.0}/annet.egg-info/requires.txt +1 -1
  20. {annet-2.5.3 → annet-2.6.0}/annet_generators/rpl_example/generator.py +3 -0
  21. {annet-2.5.3 → annet-2.6.0}/setup.py +1 -1
  22. annet-2.5.3/annet/rulebook/texts/arista.rul +0 -60
  23. {annet-2.5.3 → annet-2.6.0}/AUTHORS +0 -0
  24. {annet-2.5.3 → annet-2.6.0}/LICENSE +0 -0
  25. {annet-2.5.3 → annet-2.6.0}/MANIFEST.in +0 -0
  26. {annet-2.5.3 → annet-2.6.0}/README.md +0 -0
  27. {annet-2.5.3 → annet-2.6.0}/annet/__init__.py +0 -0
  28. {annet-2.5.3 → annet-2.6.0}/annet/adapters/__init__.py +0 -0
  29. {annet-2.5.3 → annet-2.6.0}/annet/adapters/fetchers/__init__.py +0 -0
  30. {annet-2.5.3 → annet-2.6.0}/annet/adapters/fetchers/stub/__init__.py +0 -0
  31. {annet-2.5.3 → annet-2.6.0}/annet/adapters/fetchers/stub/fetcher.py +0 -0
  32. {annet-2.5.3 → annet-2.6.0}/annet/adapters/file/__init__.py +0 -0
  33. {annet-2.5.3 → annet-2.6.0}/annet/adapters/file/provider.py +0 -0
  34. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/__init__.py +0 -0
  35. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/__init__.py +0 -0
  36. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/adapter.py +0 -0
  37. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/client.py +0 -0
  38. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/query.py +0 -0
  39. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/status_client.py +0 -0
  40. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/common/storage_opts.py +0 -0
  41. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/provider.py +0 -0
  42. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v24/__init__.py +0 -0
  43. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v24/models.py +0 -0
  44. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v24/storage.py +0 -0
  45. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v37/__init__.py +0 -0
  46. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v37/models.py +0 -0
  47. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v37/storage.py +0 -0
  48. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v41/__init__.py +0 -0
  49. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v41/models.py +0 -0
  50. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v41/storage.py +0 -0
  51. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v42/__init__.py +0 -0
  52. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v42/models.py +0 -0
  53. {annet-2.5.3 → annet-2.6.0}/annet/adapters/netbox/v42/storage.py +0 -0
  54. {annet-2.5.3 → annet-2.6.0}/annet/annlib/__init__.py +0 -0
  55. {annet-2.5.3 → annet-2.6.0}/annet/annlib/command.py +0 -0
  56. {annet-2.5.3 → annet-2.6.0}/annet/annlib/diff.py +0 -0
  57. {annet-2.5.3 → annet-2.6.0}/annet/annlib/errors.py +0 -0
  58. {annet-2.5.3 → annet-2.6.0}/annet/annlib/filter_acl.py +0 -0
  59. {annet-2.5.3 → annet-2.6.0}/annet/annlib/jsontools.py +0 -0
  60. {annet-2.5.3 → annet-2.6.0}/annet/annlib/lib.py +0 -0
  61. {annet-2.5.3 → annet-2.6.0}/annet/annlib/netdev/__init__.py +0 -0
  62. {annet-2.5.3 → annet-2.6.0}/annet/annlib/netdev/db.py +0 -0
  63. {annet-2.5.3 → annet-2.6.0}/annet/annlib/netdev/devdb/__init__.py +0 -0
  64. {annet-2.5.3 → annet-2.6.0}/annet/annlib/netdev/views/__init__.py +0 -0
  65. {annet-2.5.3 → annet-2.6.0}/annet/annlib/netdev/views/dump.py +0 -0
  66. {annet-2.5.3 → annet-2.6.0}/annet/annlib/output.py +0 -0
  67. {annet-2.5.3 → annet-2.6.0}/annet/annlib/patching.py +0 -0
  68. {annet-2.5.3 → annet-2.6.0}/annet/annlib/rbparser/__init__.py +0 -0
  69. {annet-2.5.3 → annet-2.6.0}/annet/annlib/rbparser/acl.py +0 -0
  70. {annet-2.5.3 → annet-2.6.0}/annet/annlib/rbparser/deploying.py +0 -0
  71. {annet-2.5.3 → annet-2.6.0}/annet/annlib/rbparser/ordering.py +0 -0
  72. {annet-2.5.3 → annet-2.6.0}/annet/annlib/rbparser/syntax.py +0 -0
  73. {annet-2.5.3 → annet-2.6.0}/annet/annlib/rulebook/__init__.py +0 -0
  74. {annet-2.5.3 → annet-2.6.0}/annet/annlib/tabparser.py +0 -0
  75. {annet-2.5.3 → annet-2.6.0}/annet/annlib/types.py +0 -0
  76. {annet-2.5.3 → annet-2.6.0}/annet/api/__init__.py +0 -0
  77. {annet-2.5.3 → annet-2.6.0}/annet/argparse.py +0 -0
  78. {annet-2.5.3 → annet-2.6.0}/annet/bgp_models.py +0 -0
  79. {annet-2.5.3 → annet-2.6.0}/annet/cli.py +0 -0
  80. {annet-2.5.3 → annet-2.6.0}/annet/cli_args.py +0 -0
  81. {annet-2.5.3 → annet-2.6.0}/annet/configs/context.yml +0 -0
  82. {annet-2.5.3 → annet-2.6.0}/annet/configs/logging.yaml +0 -0
  83. {annet-2.5.3 → annet-2.6.0}/annet/connectors.py +0 -0
  84. {annet-2.5.3 → annet-2.6.0}/annet/deploy.py +0 -0
  85. {annet-2.5.3 → annet-2.6.0}/annet/deploy_ui.py +0 -0
  86. {annet-2.5.3 → annet-2.6.0}/annet/diff.py +0 -0
  87. {annet-2.5.3 → annet-2.6.0}/annet/executor.py +0 -0
  88. {annet-2.5.3 → annet-2.6.0}/annet/filtering.py +0 -0
  89. {annet-2.5.3 → annet-2.6.0}/annet/gen.py +0 -0
  90. {annet-2.5.3 → annet-2.6.0}/annet/generators/base.py +0 -0
  91. {annet-2.5.3 → annet-2.6.0}/annet/generators/common/__init__.py +0 -0
  92. {annet-2.5.3 → annet-2.6.0}/annet/generators/common/initial.py +0 -0
  93. {annet-2.5.3 → annet-2.6.0}/annet/generators/entire.py +0 -0
  94. {annet-2.5.3 → annet-2.6.0}/annet/generators/exceptions.py +0 -0
  95. {annet-2.5.3 → annet-2.6.0}/annet/generators/jsonfragment.py +0 -0
  96. {annet-2.5.3 → annet-2.6.0}/annet/generators/partial.py +0 -0
  97. {annet-2.5.3 → annet-2.6.0}/annet/generators/perf.py +0 -0
  98. {annet-2.5.3 → annet-2.6.0}/annet/generators/ref.py +0 -0
  99. {annet-2.5.3 → annet-2.6.0}/annet/generators/result.py +0 -0
  100. {annet-2.5.3 → annet-2.6.0}/annet/hardware.py +0 -0
  101. {annet-2.5.3 → annet-2.6.0}/annet/implicit.py +0 -0
  102. {annet-2.5.3 → annet-2.6.0}/annet/lib.py +0 -0
  103. {annet-2.5.3 → annet-2.6.0}/annet/mesh/__init__.py +0 -0
  104. {annet-2.5.3 → annet-2.6.0}/annet/mesh/basemodel.py +0 -0
  105. {annet-2.5.3 → annet-2.6.0}/annet/mesh/device_models.py +0 -0
  106. {annet-2.5.3 → annet-2.6.0}/annet/mesh/executor.py +0 -0
  107. {annet-2.5.3 → annet-2.6.0}/annet/mesh/match_args.py +0 -0
  108. {annet-2.5.3 → annet-2.6.0}/annet/mesh/models_converter.py +0 -0
  109. {annet-2.5.3 → annet-2.6.0}/annet/mesh/peer_models.py +0 -0
  110. {annet-2.5.3 → annet-2.6.0}/annet/mesh/port_processor.py +0 -0
  111. {annet-2.5.3 → annet-2.6.0}/annet/mesh/registry.py +0 -0
  112. {annet-2.5.3 → annet-2.6.0}/annet/output.py +0 -0
  113. {annet-2.5.3 → annet-2.6.0}/annet/patching.py +0 -0
  114. {annet-2.5.3 → annet-2.6.0}/annet/reference.py +0 -0
  115. {annet-2.5.3 → annet-2.6.0}/annet/rpl/__init__.py +0 -0
  116. {annet-2.5.3 → annet-2.6.0}/annet/rpl/action.py +0 -0
  117. {annet-2.5.3 → annet-2.6.0}/annet/rpl/condition.py +0 -0
  118. {annet-2.5.3 → annet-2.6.0}/annet/rpl/match_builder.py +0 -0
  119. {annet-2.5.3 → annet-2.6.0}/annet/rpl/policy.py +0 -0
  120. {annet-2.5.3 → annet-2.6.0}/annet/rpl/result.py +0 -0
  121. {annet-2.5.3 → annet-2.6.0}/annet/rpl/routemap.py +0 -0
  122. {annet-2.5.3 → annet-2.6.0}/annet/rpl/statement_builder.py +0 -0
  123. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/__init__.py +0 -0
  124. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/aspath.py +0 -0
  125. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/community.py +0 -0
  126. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/cumulus_frr.py +0 -0
  127. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/entities.py +0 -0
  128. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/execute.py +0 -0
  129. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/policy.py +0 -0
  130. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/prefix_lists.py +0 -0
  131. {annet-2.5.3 → annet-2.6.0}/annet/rpl_generators/rd.py +0 -0
  132. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/__init__.py +0 -0
  133. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/arista/__init__.py +0 -0
  134. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/arista/aaa.py +0 -0
  135. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/arista/iface.py +0 -0
  136. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/aruba/__init__.py +0 -0
  137. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/aruba/ap_env.py +0 -0
  138. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/aruba/misc.py +0 -0
  139. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/b4com/__init__.py +0 -0
  140. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/b4com/file.py +0 -0
  141. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/b4com/iface.py +0 -0
  142. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/cisco/__init__.py +0 -0
  143. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/cisco/iface.py +0 -0
  144. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/cisco/misc.py +0 -0
  145. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/cisco/vlandb.py +0 -0
  146. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/common.py +0 -0
  147. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/deploying.py +0 -0
  148. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/huawei/__init__.py +0 -0
  149. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/huawei/aaa.py +0 -0
  150. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/huawei/bgp.py +0 -0
  151. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/huawei/iface.py +0 -0
  152. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/huawei/misc.py +0 -0
  153. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/huawei/vlandb.py +0 -0
  154. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/juniper/__init__.py +0 -0
  155. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/nexus/__init__.py +0 -0
  156. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/nexus/iface.py +0 -0
  157. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/patching.py +0 -0
  158. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/routeros/__init__.py +0 -0
  159. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/routeros/file.py +0 -0
  160. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/arista.deploy +0 -0
  161. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/arista.order +0 -0
  162. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/aruba.deploy +0 -0
  163. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/aruba.order +0 -0
  164. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/aruba.rul +0 -0
  165. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/b4com.deploy +0 -0
  166. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/b4com.order +0 -0
  167. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/b4com.rul +0 -0
  168. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/cisco.deploy +0 -0
  169. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/cisco.order +0 -0
  170. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/cisco.rul +0 -0
  171. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/huawei.deploy +0 -0
  172. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/huawei.order +0 -0
  173. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/huawei.rul +0 -0
  174. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/juniper.order +0 -0
  175. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/juniper.rul +0 -0
  176. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/nexus.deploy +0 -0
  177. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/nexus.order +0 -0
  178. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/nexus.rul +0 -0
  179. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/nokia.rul +0 -0
  180. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/optixtrans.deploy +0 -0
  181. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/optixtrans.order +0 -0
  182. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/optixtrans.rul +0 -0
  183. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/pc.deploy +0 -0
  184. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/pc.order +0 -0
  185. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/pc.rul +0 -0
  186. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/ribbon.deploy +0 -0
  187. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/ribbon.rul +0 -0
  188. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/routeros.order +0 -0
  189. {annet-2.5.3 → annet-2.6.0}/annet/rulebook/texts/routeros.rul +0 -0
  190. {annet-2.5.3 → annet-2.6.0}/annet/storage.py +0 -0
  191. {annet-2.5.3 → annet-2.6.0}/annet/text_term_format.py +0 -0
  192. {annet-2.5.3 → annet-2.6.0}/annet/tracing.py +0 -0
  193. {annet-2.5.3 → annet-2.6.0}/annet/types.py +0 -0
  194. {annet-2.5.3 → annet-2.6.0}/annet.egg-info/dependency_links.txt +0 -0
  195. {annet-2.5.3 → annet-2.6.0}/annet.egg-info/entry_points.txt +0 -0
  196. {annet-2.5.3 → annet-2.6.0}/annet.egg-info/top_level.txt +0 -0
  197. {annet-2.5.3 → annet-2.6.0}/annet_generators/__init__.py +0 -0
  198. {annet-2.5.3 → annet-2.6.0}/annet_generators/example/__init__.py +0 -0
  199. {annet-2.5.3 → annet-2.6.0}/annet_generators/example/lldp.py +0 -0
  200. {annet-2.5.3 → annet-2.6.0}/annet_generators/mesh_example/__init__.py +0 -0
  201. {annet-2.5.3 → annet-2.6.0}/annet_generators/mesh_example/bgp.py +0 -0
  202. {annet-2.5.3 → annet-2.6.0}/annet_generators/mesh_example/mesh_logic.py +0 -0
  203. {annet-2.5.3 → annet-2.6.0}/annet_generators/rpl_example/__init__.py +0 -0
  204. {annet-2.5.3 → annet-2.6.0}/annet_generators/rpl_example/items.py +0 -0
  205. {annet-2.5.3 → annet-2.6.0}/annet_generators/rpl_example/mesh.py +0 -0
  206. {annet-2.5.3 → annet-2.6.0}/annet_generators/rpl_example/route_policy.py +0 -0
  207. {annet-2.5.3 → annet-2.6.0}/requirements.txt +0 -0
  208. {annet-2.5.3 → annet-2.6.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: annet
3
- Version: 2.5.3
3
+ Version: 2.6.0
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
@@ -21,7 +21,7 @@ Requires-Dist: yarl>=1.8.2
21
21
  Requires-Dist: adaptix==3.0.0b7
22
22
  Requires-Dist: dataclass-rest==0.4
23
23
  Provides-Extra: netbox
24
- Requires-Dist: annetbox[sync]>=0.2.2; extra == "netbox"
24
+ Requires-Dist: annetbox[sync]>=0.3.0; extra == "netbox"
25
25
  Dynamic: home-page
26
26
  Dynamic: license
27
27
  Dynamic: license-file
@@ -8,6 +8,7 @@ _VENDORS = {
8
8
  "cisco": "Cisco",
9
9
  "catalyst": "Cisco Catalyst",
10
10
  "nexus": "Cisco Nexus",
11
+ "iosxr": "Cisco XR",
11
12
  "huawei": "Huawei",
12
13
  "optixtrans": "Huawei OptiXtrans",
13
14
  "juniper": "Juniper",
@@ -19,6 +19,11 @@ class Entity(DumpableView):
19
19
  return self.name
20
20
 
21
21
 
22
+ @dataclass
23
+ class EntityWithSlug(Entity):
24
+ slug: str
25
+
26
+
22
27
  @dataclass
23
28
  class Label:
24
29
  value: str
@@ -82,7 +87,7 @@ class IpAddress(DumpableView, Generic[_PrefixT]):
82
87
  family: IpFamily
83
88
  address: str
84
89
  status: Label
85
- tags: List[Entity]
90
+ tags: List[EntityWithSlug]
86
91
  created: datetime
87
92
  last_updated: datetime
88
93
  prefix: Optional[_PrefixT] = None
@@ -135,12 +140,14 @@ class Interface(Entity, Generic[_IpAddressT]):
135
140
  mode: Optional[InterfaceMode]
136
141
  untagged_vlan: Optional[InterfaceVlan]
137
142
  tagged_vlans: Optional[List[InterfaceVlan]]
143
+ tags: List[EntityWithSlug] = field(default_factory=list)
138
144
  display: str = ""
139
145
  ip_addresses: List[_IpAddressT] = field(default_factory=list)
140
146
  vrf: Optional[Entity] = None
141
147
  mtu: int | None = None
142
148
  lag: Entity | None = None
143
149
  lag_min_links: int | None = None
150
+ speed: int | None = None
144
151
 
145
152
  def add_addr(self, address_mask: str, vrf: str | None) -> None:
146
153
  for existing_addr in self.ip_addresses:
@@ -186,10 +193,11 @@ class NetboxDevice(Entity, Generic[_InterfaceT]):
186
193
  primary_ip: Optional[DeviceIp]
187
194
  primary_ip4: Optional[DeviceIp]
188
195
  primary_ip6: Optional[DeviceIp]
189
- tags: List[Entity]
196
+ tags: List[EntityWithSlug]
190
197
  custom_fields: Dict[str, Any]
191
198
  created: datetime
192
199
  last_updated: datetime
200
+ cluster: Optional[Entity]
193
201
 
194
202
  fqdn: str
195
203
  hostname: str
@@ -161,6 +161,7 @@ class BaseNetboxStorage(
161
161
  return self._id_devices[obj_id]
162
162
 
163
163
  device = self.netbox.get_device(obj_id)
164
+ self._fill_device_interfaces([device])
164
165
  self._record_device(device)
165
166
  return device
166
167
 
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env python3
2
+ import logging
2
3
  import sys
3
4
 
4
5
  import annet
@@ -18,8 +19,14 @@ def main():
18
19
  parser.add_commands(parser.find_subcommands(cli.list_subcommands()))
19
20
  try:
20
21
  return parser.dispatch(pre_call=annet.init, add_help_command=True)
21
- except (generators.GeneratorError, annet.ExecError):
22
+ except (generators.GeneratorError, annet.ExecError) as e:
23
+ logging.error(e)
22
24
  return 1
25
+ except BaseException as e:
26
+ if formatted_output := getattr(e, "formatted_output", None):
27
+ logging.error(formatted_output)
28
+ return 1
29
+ raise e
23
30
 
24
31
 
25
32
  if __name__ == "__main__":
@@ -6,6 +6,7 @@
6
6
  "Cisco.ASR": " ASR",
7
7
  "Cisco.ASR.ASR9000": " 9\\d{3}",
8
8
  "Cisco.XRV": "XRv",
9
+ "Cisco.XR": " 8[\\d\\d\\d]",
9
10
  "Cisco.Catalyst": " (Catalyst |WS-C)",
10
11
  "Cisco.Catalyst.C2900": "29\\d\\d",
11
12
  "Cisco.Catalyst.C2900.C2950": "2950",
@@ -75,6 +75,8 @@ class HardwareView(HardwareLeaf):
75
75
  def hw_to_vendor(hw: HardwareView) -> Optional[str]:
76
76
  if hw.Nexus:
77
77
  return "nexus"
78
+ elif hw.Cisco.XR or hw.Cisco.ASR or hw.Cisco.XRV:
79
+ return "iosxr"
78
80
  elif hw.Cisco:
79
81
  return "cisco"
80
82
  elif hw.OptiXtrans:
@@ -108,6 +110,7 @@ def vendor_to_hw(vendor):
108
110
  "cisco": "Cisco",
109
111
  "catalyst": "Cisco Catalyst",
110
112
  "nexus": "Cisco Nexus",
113
+ "iosxr": "Cisco XR",
111
114
  "huawei": "Huawei",
112
115
  "optixtrans": "Huawei OptiXtrans",
113
116
  "juniper": "Juniper",
@@ -3,6 +3,7 @@ VENDOR_REVERSES = {
3
3
  "h3c": "undo",
4
4
  "optixtrans": "undo",
5
5
  "cisco": "no",
6
+ "iosxr": "no",
6
7
  "nexus": "no",
7
8
  "juniper": "delete",
8
9
  "arista": "no",
@@ -18,6 +19,7 @@ VENDOR_DIFF = {
18
19
  "huawei": "common.default_diff",
19
20
  "optixtrans": "common.default_diff",
20
21
  "cisco": "common.default_diff",
22
+ "iosxr": "common.default_diff",
21
23
  "nexus": "common.default_diff",
22
24
  "juniper": "juniper.default_diff",
23
25
  "arista": "common.default_diff",
@@ -33,6 +35,7 @@ VENDOR_DIFF_ORDERED = {
33
35
  "huawei": "common.ordered_diff",
34
36
  "optixtrans": "common.ordered_diff",
35
37
  "cisco": "common.ordered_diff",
38
+ "iosxr": "common.ordered_diff",
36
39
  "nexus": "common.ordered_diff",
37
40
  "juniper": "juniper.ordered_diff",
38
41
  "arista": "common.ordered_diff",
@@ -49,6 +52,7 @@ VENDOR_EXIT = {
49
52
  "h3c": "quit",
50
53
  "optixtrans": "quit",
51
54
  "cisco": "exit",
55
+ "iosxr": "exit",
52
56
  "nexus": "exit",
53
57
  "arista": "exit",
54
58
  "juniper": "",
@@ -297,7 +297,7 @@ def apply(hw, do_commit, do_finalize, **_):
297
297
  after.add_cmd(Command("abort")) # просто exit оставит висеть configure session
298
298
  if do_finalize:
299
299
  after.add_cmd(Command("write memory"))
300
- elif hw.ASR or hw.XRV:
300
+ elif hw.ASR or hw.XRV or hw.XR:
301
301
  # коммит сам сохраняет изменения в стартап do_finalize не применим
302
302
  before.add_cmd(Command("configure exclusive"))
303
303
  if do_commit:
@@ -197,7 +197,7 @@ def _run_partial_generator(gen: "PartialGenerator", run_args: GeneratorPartialRu
197
197
  raise
198
198
  except Exception as err:
199
199
  filename, lineno = gen.get_running_line()
200
- logger.exception("Generator error in file '%s:%i'", filename, lineno)
200
+ logger.error("Generator error in file '%s:%i'", filename, lineno)
201
201
  raise GeneratorError(f"{gen} on {device}") from err
202
202
 
203
203
  fmtr = tabparser.make_formatter(device.hw)
@@ -15,13 +15,14 @@ import tempfile
15
15
  import time
16
16
  import traceback
17
17
  import warnings
18
- from typing import Any, List, Optional, Type
18
+ from typing import Any, List, Optional, Type, Callable
19
19
  from uuid import uuid4
20
20
 
21
21
  from contextlog import get_logger
22
22
 
23
23
  import annet
24
24
  from annet import tracing
25
+ from annet.connectors import Connector
25
26
  from annet.lib import catch_ctrl_c, find_exc_in_stack
26
27
  from annet.output import capture_output
27
28
  from annet.tracing import tracing_connector
@@ -38,6 +39,20 @@ class PoolWorkerTask:
38
39
  payload: Optional[Any] = None
39
40
 
40
41
 
42
+ class _PickleSafeTracebackFormatterConnector(Connector[Callable[[BaseException], str]]):
43
+ name = "PickleSafeTraceBackFormatter"
44
+ ep_name = "pickle_safe_traceback_formatter"
45
+
46
+ def _get_default(self) -> Callable[[], Callable[[BaseException], str]]:
47
+ def wrapper():
48
+ return lambda x: "".join(traceback.format_exception(x))
49
+
50
+ return wrapper
51
+
52
+
53
+ pickle_safe_traceback_formatter_connector = _PickleSafeTracebackFormatterConnector()
54
+
55
+
41
56
  class PickleSafeException(Exception):
42
57
  """An exception that can be safely pickled and passed between processes."""
43
58
 
@@ -59,9 +74,14 @@ class PickleSafeException(Exception):
59
74
  pretty_lines.append(self.formatted_output)
60
75
  return "\n".join(pretty_lines)
61
76
 
62
- @staticmethod
63
- def from_exc(orig_exc: Exception, device_id: str, formatted_output: str) -> "PickleSafeException":
64
- return PickleSafeException(orig_exc.__class__, str(orig_exc), device_id, formatted_output)
77
+ @classmethod
78
+ def from_exc(cls, orig_exc: Exception, device_id: str) -> "PickleSafeException":
79
+ return PickleSafeException(
80
+ orig_exc.__class__,
81
+ str(orig_exc),
82
+ device_id,
83
+ pickle_safe_traceback_formatter_connector.get()(orig_exc)
84
+ )
65
85
 
66
86
 
67
87
  @catch_ctrl_c
@@ -164,7 +184,7 @@ def _pool_worker(pool, index, task_queue, done_queue):
164
184
  except KeyboardInterrupt: # pylint: disable=try-except-raise
165
185
  raise
166
186
  except Exception as exc:
167
- safe_exc = PickleSafeException.from_exc(exc, task.payload, traceback.format_exc())
187
+ safe_exc = PickleSafeException.from_exc(exc, task.payload)
168
188
  ret_exc = safe_exc
169
189
  task_result.exc = safe_exc
170
190
  task_result.result = None
@@ -301,11 +321,10 @@ class Parallel:
301
321
  **self.kwargs
302
322
  )
303
323
  except Exception as exc:
324
+ safe_exc = PickleSafeException.from_exc(exc, device_id)
304
325
  if not tolerate_fails:
305
- raise
306
- exc.device_id = device_id
307
- exc.formatted_output = traceback.format_exc()
308
- task_result.exc = exc
326
+ raise safe_exc
327
+ task_result.exc = safe_exc
309
328
  if self.capture_output:
310
329
  task_result.extra["cap_stdout"] = cap_stdout.read()
311
330
  task_result.extra["cap_stderr"] = cap_stderr.read()
@@ -0,0 +1,82 @@
1
+ description %global
2
+
3
+
4
+ qos profile *
5
+ ~ %global
6
+
7
+ username * ssh-key
8
+ username * %logic=arista.aaa.user
9
+
10
+ aaa group ~
11
+ ~ %global
12
+
13
+
14
+ role *
15
+ ~ %global
16
+
17
+
18
+ vrf instance *
19
+ ~ %global
20
+
21
+
22
+ interface * %logic=arista.iface.permanent
23
+ no switchport
24
+ description *
25
+ channel-group *
26
+ lacp rate *
27
+ service-profile *
28
+ ~ %global
29
+
30
+
31
+ ip access-list standard *
32
+ * %logic=common.undo_redo
33
+
34
+ ipv6 access-list standard *
35
+ * %logic=common.undo_redo
36
+
37
+ ipv6 access-list *
38
+ * %logic=common.undo_redo
39
+
40
+
41
+ # ios-like way of configuring prefix lists
42
+ # should be kept above a eos-native one in arista.rul
43
+ # since beginnig of commands are the same
44
+ # if you use it keep all prefix lists in this format
45
+
46
+ ip prefix-list * seq * %logic=common.undo_redo
47
+ ipv6 prefix-list * seq * %logic=common.undo_redo
48
+
49
+
50
+ # arista eos native way of configuring prefix lists
51
+ # should be below to not collide with ios-like one
52
+ # only one format is supported at the time for one family
53
+ # prefer this one over the ios-like one
54
+
55
+ ip prefix-list *
56
+ seq * %logic=common.undo_redo
57
+
58
+ ipv6 prefix-list *
59
+ seq * %logic=common.undo_redo
60
+
61
+
62
+ route-map * * *
63
+ ~ %global
64
+
65
+ router bfd
66
+ ~ %global
67
+
68
+
69
+ router bgp *
70
+ no bgp default *
71
+ neighbor * maximum-routes
72
+ ! no neighbor * shutdown
73
+ ~ %global
74
+
75
+ ip load-sharing trident fields * %logic=common.default_instead_undo
76
+
77
+ management *
78
+ ~ %global
79
+
80
+
81
+ no ~ %global
82
+ ~ %global
@@ -0,0 +1,27 @@
1
+ # Рулбук деплоя на устройства
2
+ #
3
+ # Операторы:
4
+ # * Один аргумент
5
+ # ~ Несколько аргументов (минимум один)
6
+ #
7
+ # Параметры:
8
+ # %timeout=... Таймаут выполнения команды (в секундах, по умолчанию 30)
9
+ #
10
+ # Ответы на вопросы
11
+ #
12
+ # <команда>
13
+ # dialog: <вопрос> ::: <ответ> <параметры>
14
+ #
15
+ # Если <вопрос> заключён в слеши (//), то воспринимается как регулярка, иначе - точное совпадение.
16
+ # Параметы:
17
+ # %send_nl=... Посылать ли перевод строки после ответа (bool, по умолчанию true)
18
+ # -----
19
+
20
+ crypto key generate rsa %timeout=60
21
+ dialog: Do you really want to replace them? [yes/no]: ::: no
22
+ dialog: How many bits in the modulus [512]: ::: 2048
23
+ no username * privilege * secret * *
24
+ dialog: This operation will remove all username related configurations with same name.Do you want to continue? [confirm] ::: Y %send_nl=0
25
+
26
+ copy running-config startup-config
27
+ dialog: Destination filename [startup-config]? ::: startup-config
@@ -0,0 +1,85 @@
1
+ # В этом файле определяется порядок команд, в котором их следует подавать на устройство.
2
+ # - Если порядок команды не важен - ее можно не писать сюда совсем.
3
+ # - Если команда начинается с undo и прописан параметр %order_reverse - команда считается
4
+ # обратной, но занимает место между прямыми там, где указано.
5
+
6
+ banner login %order_reverse
7
+
8
+ # Фичи должны быть включены прежде всего
9
+ feature
10
+ # За ним сервисы
11
+ service
12
+
13
+ aaa new-model
14
+ aaa ~
15
+
16
+ no password strength-check
17
+ username
18
+ tacacs-server
19
+
20
+ radius
21
+ radius-server
22
+ dot1x
23
+
24
+ privilege
25
+ file
26
+
27
+ ip access-list
28
+ ipv6 access-list
29
+ class-map
30
+ policy-map
31
+ system qos
32
+ control-plane
33
+
34
+ snmp-server source-interface
35
+ snmp-server user
36
+ snmp-server host
37
+ snmp-server enable
38
+ snmp-server context
39
+ snmp-server community
40
+ snmp-server mib
41
+
42
+ ntp distribute
43
+ ntp server
44
+ ntp commit
45
+
46
+ vlan
47
+ vlan group
48
+
49
+ spanning-tree
50
+
51
+ # перед тем, как менять mtu на интерфейсах, надо выставить максимальный
52
+ no system jumbomtu %order_reverse
53
+ system jumbomtu
54
+
55
+ service dhcp
56
+ ip dhcp relay
57
+ ipv6 dhcp relay
58
+
59
+ vrf context
60
+
61
+ interface */Vlan\d+/
62
+ interface *
63
+ no switchport
64
+ encapsulation
65
+ vrf member
66
+ ip
67
+ ipv6
68
+ no ipv6 nd %order_reverse
69
+ ipv6 nd
70
+ ~
71
+ channel-group
72
+
73
+ interface */\S+\.\d+/
74
+
75
+ route-map
76
+
77
+ # удалять eth-trunk можно только после того, как вычистим member interfaces
78
+ undo interface */port-channel\d+/ %order_reverse
79
+
80
+ # remote as of neighbors should be assigned before peer-group, the rule is applied to neighbors, not peer-groups
81
+ router bgp
82
+ neighbor */[\da-f\.\:]+/ remote-as
83
+ neighbor */[\da-f\.\:]+/ peer-group
84
+
85
+ line
@@ -0,0 +1,110 @@
1
+ # Операторы:
2
+ # * Один аргумент в undo
3
+ # ~ Несколько аргументов (минимум один) в undo
4
+ #
5
+ # Параметры:
6
+ # %global Команда действует на любом уровне ниже
7
+ # %logic=... Кастомная функция обработки правила
8
+ # %diff_logic=... Кастомная функция построения диффа.
9
+ # данная функция работает для подблоков (в отличие от %logic)
10
+ # %comment=... Добавить коммент после строки который будет видно с опцией patch --add-comments
11
+ # Сделано в основном для того чтобы генерировать специальные команды для наливки
12
+ # -----
13
+
14
+ ip domain-name *
15
+ hostname *
16
+
17
+ banner login * %logic=cisco.misc.banner_login
18
+
19
+ ip community-list standard ~
20
+
21
+ !vrf context management
22
+ vrf context *
23
+
24
+ vlan group * vlan-list %logic=cisco.vlandb.simple
25
+ vlan */[^\d].*/
26
+ vlan %logic=cisco.vlandb.simple
27
+ name
28
+
29
+ ip ssh version 2 %logic=cisco.misc.ssh_key
30
+
31
+ # ordering of SNMP blocks
32
+ ip access-list ~
33
+ snmp-server view ~
34
+ snmp-server community ~
35
+ snmp-server host ~
36
+ # Deleting a user using either SNMP or the CLI results in the user being deleted for both SNMP and the CLI.
37
+ # User-role mapping changes are synchronized in SNMP and the CLI.
38
+ !snmp-server user admin ~
39
+ !snmp-server user *
40
+ # Disabling this SNMP option throws WARNING which stops mpdaemon set-up process
41
+ no snmp-server sysobjectid type stack-oid
42
+
43
+ !interface */(mgmt|ipmi|Vlan1$)/
44
+
45
+ interface Loopback
46
+ ipv6 address *
47
+ ip address ~
48
+ ! no ip address
49
+
50
+ # SVI/Subifs/Lagg
51
+ interface */(Vlan|Ethernet.*\.|port-channel.*\.?)\d+$/ %diff_logic=cisco.iface.diff
52
+ vrf member
53
+ ipv6 link-local
54
+ ipv6 address *
55
+ ipv6 nd ~ %logic=cisco.misc.no_ipv6_nd_suppress_ra
56
+ ip address ~
57
+ ! no ip address
58
+ mtu
59
+
60
+ # Physical
61
+ interface */\w*Ethernet[0-9\/]+$/ %logic=common.permanent %diff_logic=cisco.iface.diff
62
+ switchport mode
63
+ switchport trunk native vlan
64
+ switchport access vlan
65
+ switchport trunk allowed vlan %logic=cisco.vlandb.swtrunk
66
+ vrf member
67
+ ipv6 link-local
68
+ ipv6 address *
69
+ ip address ~
70
+ ! no ip address
71
+ channel-group
72
+ mtu
73
+ storm-control * level
74
+ spanning-tree portfast
75
+
76
+ router bgp
77
+ router-id
78
+ vrf *
79
+ router-id
80
+ address-family ~
81
+ maximum-paths
82
+ neighbor ~
83
+ update-source
84
+
85
+ policy-map type qos *
86
+ class * %ordered
87
+ ~
88
+
89
+ prefix-set *
90
+ ~ %rewrite %global
91
+
92
+ as-path-set *
93
+ ~ %rewrite %global
94
+
95
+ community-set *
96
+ ~ %rewrite %global
97
+
98
+ route-policy *
99
+ ~ %rewrite %global
100
+
101
+ line ~
102
+ exec-timeout
103
+ transport input
104
+
105
+ description %global
106
+
107
+ no ~ %global
108
+ ~ %global
109
+
110
+ # vim: set syntax=annrulebook:
@@ -23,7 +23,7 @@ def make_formatter(hw, **kwargs):
23
23
  cls = OptixtransFormatter
24
24
  elif hw.Huawei:
25
25
  cls = HuaweiFormatter
26
- elif hw.Cisco.ASR or hw.Cisco.XRV:
26
+ elif hw.Cisco.ASR or hw.Cisco.XRV or hw.Cisco.XR:
27
27
  cls = AsrFormatter
28
28
  elif hw.Nexus:
29
29
  cls = NexusFormatter
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: annet
3
- Version: 2.5.3
3
+ Version: 2.6.0
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
@@ -21,7 +21,7 @@ Requires-Dist: yarl>=1.8.2
21
21
  Requires-Dist: adaptix==3.0.0b7
22
22
  Requires-Dist: dataclass-rest==0.4
23
23
  Provides-Extra: netbox
24
- Requires-Dist: annetbox[sync]>=0.2.2; extra == "netbox"
24
+ Requires-Dist: annetbox[sync]>=0.3.0; extra == "netbox"
25
25
  Dynamic: home-page
26
26
  Dynamic: license
27
27
  Dynamic: license-file
@@ -173,6 +173,9 @@ annet/rulebook/texts/cisco.rul
173
173
  annet/rulebook/texts/huawei.deploy
174
174
  annet/rulebook/texts/huawei.order
175
175
  annet/rulebook/texts/huawei.rul
176
+ annet/rulebook/texts/iosxr.deploy
177
+ annet/rulebook/texts/iosxr.order
178
+ annet/rulebook/texts/iosxr.rul
176
179
  annet/rulebook/texts/juniper.order
177
180
  annet/rulebook/texts/juniper.rul
178
181
  annet/rulebook/texts/nexus.deploy
@@ -13,4 +13,4 @@ adaptix==3.0.0b7
13
13
  dataclass-rest==0.4
14
14
 
15
15
  [netbox]
16
- annetbox[sync]>=0.2.2
16
+ annetbox[sync]>=0.3.0
@@ -30,6 +30,9 @@ class CommunityGenerator(CommunityListGenerator):
30
30
 
31
31
 
32
32
  class PolicyGenerator(RoutingPolicyGenerator):
33
+ def get_prefix_lists(self, device: Any) -> list[IpPrefixList]:
34
+ return PREFIX_LISTS
35
+
33
36
  def get_policies(self, device: Any) -> list[RoutingPolicy]:
34
37
  return get_policies(
35
38
  routemap=routemap,
@@ -44,7 +44,7 @@ if __name__ == "__main__":
44
44
  ],
45
45
  },
46
46
  extras_require={
47
- "netbox": ["annetbox[sync]>=0.2.2"],
47
+ "netbox": ["annetbox[sync]>=0.3.0"],
48
48
  },
49
49
  python_requires=">=3.10",
50
50
  install_requires=requirements(),