Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
GÉANT Service Orchestrator
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
GÉANT Orchestration and Automation Team
GAP
GÉANT Service Orchestrator
Commits
5e008e08
Commit
5e008e08
authored
2 years ago
by
JORGE SASIAIN
Browse files
Options
Downloads
Patches
Plain Diff
Some IPAM calls for A/AAAA records
parent
71d2b14f
No related branches found
No related tags found
1 merge request
!9
Ipam service
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
gso/services/_ipam.py
+71
-19
71 additions, 19 deletions
gso/services/_ipam.py
gso/services/ipam.py
+30
-11
30 additions, 11 deletions
gso/services/ipam.py
with
101 additions
and
30 deletions
gso/services/_ipam.py
+
71
−
19
View file @
5e008e08
...
@@ -4,6 +4,7 @@ import json
...
@@ -4,6 +4,7 @@ import json
import
ipaddress
import
ipaddress
from
pydantic
import
BaseSettings
from
pydantic
import
BaseSettings
from
typing
import
Union
from
typing
import
Union
import
random
from
gso
import
settings
from
gso
import
settings
...
@@ -96,7 +97,7 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
...
@@ -96,7 +97,7 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
assert
ip_version
in
[
4
,
6
]
assert
ip_version
in
[
4
,
6
]
endpoint
=
'
network
'
if
ip_version
==
4
else
'
ipv6network
'
endpoint
=
'
network
'
if
ip_version
==
4
else
'
ipv6network
'
_
ipv4_req_payload
=
{
ipv4_req_payload
=
{
"
network
"
:
{
"
network
"
:
{
"
_object_function
"
:
"
next_available_network
"
,
"
_object_function
"
:
"
next_available_network
"
,
"
_parameters
"
:
{
"
_parameters
"
:
{
...
@@ -110,7 +111,7 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
...
@@ -110,7 +111,7 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
}
}
}
}
_
ipv6_req_payload
=
{
ipv6_req_payload
=
{
"
network
"
:
{
"
network
"
:
{
"
_object_function
"
:
"
next_available_network
"
,
"
_object_function
"
:
"
next_available_network
"
,
"
_parameters
"
:
{
"
_parameters
"
:
{
...
@@ -124,12 +125,12 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
...
@@ -124,12 +125,12 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
}
}
}
}
_
req_payload
=
_
ipv4_req_payload
if
ip_version
==
4
else
_
ipv6_req_payload
req_payload
=
ipv4_req_payload
if
ip_version
==
4
else
ipv6_req_payload
r
=
requests
.
post
(
r
=
requests
.
post
(
f
'
{
_wapi
(
infoblox_params
)
}
/
{
endpoint
}
'
,
f
'
{
_wapi
(
infoblox_params
)
}
/
{
endpoint
}
'
,
params
=
{
'
_return_fields
'
:
'
network
'
},
params
=
{
'
_return_fields
'
:
'
network
'
},
json
=
_
req_payload
,
json
=
req_payload
,
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
headers
=
{
'
content-type
'
:
"
application/json
"
},
headers
=
{
'
content-type
'
:
"
application/json
"
},
verify
=
False
)
verify
=
False
)
...
@@ -145,16 +146,14 @@ def allocate_service_ipv4_network(service_type):
...
@@ -145,16 +146,14 @@ def allocate_service_ipv4_network(service_type):
oss
=
settings
.
load_oss_params
()
oss
=
settings
.
load_oss_params
()
assert
oss
.
IPAM
assert
oss
.
IPAM
ipam_params
=
oss
.
IPAM
ipam_params
=
oss
.
IPAM
# sanity: verify the service_type is a proper one
assert
hasattr
(
ipam_params
,
service_type
)
and
service_type
!=
'
INFOBLOX
'
,
"
Invalid service type.
"
assert
hasattr
(
ipam_params
,
service_type
)
and
service_type
!=
'
INFOBLOX
'
return
_allocate_network
(
ipam_params
.
INFOBLOX
,
getattr
(
ipam_params
,
service_type
).
V4
,
4
)
return
_allocate_network
(
ipam_params
.
INFOBLOX
,
getattr
(
ipam_params
,
service_type
).
V4
,
4
)
def
allocate_service_ipv6_network
(
service_type
):
def
allocate_service_ipv6_network
(
service_type
):
oss
=
settings
.
load_oss_params
()
oss
=
settings
.
load_oss_params
()
assert
oss
.
IPAM
assert
oss
.
IPAM
ipam_params
=
oss
.
IPAM
ipam_params
=
oss
.
IPAM
# sanity: verify the service_type is a proper one
assert
hasattr
(
ipam_params
,
service_type
)
and
service_type
!=
'
INFOBLOX
'
,
"
Invalid service type.
"
assert
hasattr
(
ipam_params
,
service_type
)
and
service_type
!=
'
INFOBLOX
'
return
_allocate_network
(
ipam_params
.
INFOBLOX
,
getattr
(
ipam_params
,
service_type
).
V6
,
6
)
return
_allocate_network
(
ipam_params
.
INFOBLOX
,
getattr
(
ipam_params
,
service_type
).
V6
,
6
)
def
delete_network
(
network
):
def
delete_network
(
network
):
...
@@ -193,7 +192,7 @@ def _find_next_available_ip(infoblox_params, network_ref):
...
@@ -193,7 +192,7 @@ def _find_next_available_ip(infoblox_params, network_ref):
assert
len
(
received_ip
)
==
1
assert
len
(
received_ip
)
==
1
return
received_ip
[
0
]
return
received_ip
[
0
]
def
allocate_host
(
mac
=
None
,
hostname
=
None
,
addr
=
None
,
network
=
None
):
def
allocate_host
(
mac
=
None
,
hostname
=
None
,
addr
=
None
,
network
=
None
,
service_type
=
None
):
oss
=
settings
.
load_oss_params
()
oss
=
settings
.
load_oss_params
()
assert
oss
.
IPAM
.
INFOBLOX
assert
oss
.
IPAM
.
INFOBLOX
infoblox_params
=
oss
.
IPAM
.
INFOBLOX
infoblox_params
=
oss
.
IPAM
.
INFOBLOX
...
@@ -209,7 +208,7 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
...
@@ -209,7 +208,7 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
else
:
else
:
ip_version
=
_ip_addr_version
(
addr
)
ip_version
=
_ip_addr_version
(
addr
)
_
ipv4_req_payload
=
{
ipv4_req_payload
=
{
"
ipv4addrs
"
:
[
"
ipv4addrs
"
:
[
{
{
"
ipv4addr
"
:
addr
,
"
ipv4addr
"
:
addr
,
...
@@ -221,7 +220,7 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
...
@@ -221,7 +220,7 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
"
view
"
:
"
default
"
"
view
"
:
"
default
"
}
}
_
ipv6_req_payload
=
{
ipv6_req_payload
=
{
"
ipv6addrs
"
:
[
"
ipv6addrs
"
:
[
{
{
"
ipv6addr
"
:
addr
"
ipv6addr
"
:
addr
...
@@ -232,17 +231,41 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
...
@@ -232,17 +231,41 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
"
view
"
:
"
default
"
"
view
"
:
"
default
"
}
}
_req_payload
=
_
ipv4_req_payload
if
ip_version
==
4
else
_
ipv6_req_payload
ip
_req_payload
=
ipv4_req_payload
if
ip_version
==
4
else
ipv6_req_payload
r
=
requests
.
post
(
r
=
requests
.
post
(
f
'
{
_wapi
(
infoblox_params
)
}
/record:host
'
,
f
'
{
_wapi
(
infoblox_params
)
}
/record:host
'
,
json
=
_req_payload
,
json
=
ip
_req_payload
,
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
verify
=
False
)
verify
=
False
)
assert
r
.
status_code
>=
200
and
r
.
status_code
<
300
,
f
"
HTTP error
{
r
.
status_code
}
:
{
r
.
reason
}
\n\n
{
r
.
text
}
"
assert
r
.
status_code
>=
200
and
r
.
status_code
<
300
,
f
"
HTTP error
{
r
.
status_code
}
:
{
r
.
reason
}
\n\n
{
r
.
text
}
"
assert
isinstance
(
r
.
json
(),
str
)
assert
isinstance
(
r
.
json
(),
str
)
assert
r
.
json
().
startswith
(
"
record:host/
"
)
assert
r
.
json
().
startswith
(
"
record:host/
"
)
a_record_payload
=
{
"
ipv4addr
"
:
addr
,
"
name
"
:
hostname
,
"
view
"
:
"
default
"
}
aaaa_record_payload
=
{
"
ipv6addr
"
:
addr
,
"
name
"
:
hostname
,
"
view
"
:
"
default
"
}
endpoint
=
'
record:a
'
if
ip_version
==
4
else
'
record:aaaa
'
dns_req_payload
=
a_record_payload
if
ip_version
==
4
else
aaaa_record_payload
r
=
requests
.
post
(
f
'
{
_wapi
(
infoblox_params
)
}
/
{
endpoint
}
'
,
json
=
dns_req_payload
,
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
verify
=
False
)
assert
r
.
status_code
>=
200
and
r
.
status_code
<
300
,
f
"
HTTP error
{
r
.
status_code
}
:
{
r
.
reason
}
\n\n
{
r
.
text
}
"
assert
isinstance
(
r
.
json
(),
str
)
assert
r
.
json
().
startswith
(
f
"
{
endpoint
}
/
"
)
if
ip_version
==
4
:
if
ip_version
==
4
:
return
V4HostAddress
(
v4
=
addr
)
return
V4HostAddress
(
v4
=
addr
)
else
:
else
:
...
@@ -272,7 +295,26 @@ def delete_host_by_ip(addr):
...
@@ -272,7 +295,26 @@ def delete_host_by_ip(addr):
f
'
{
_wapi
(
infoblox_params
)
}
/
{
host_ref
}
'
,
f
'
{
_wapi
(
infoblox_params
)
}
/
{
host_ref
}
'
,
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
verify
=
False
)
verify
=
False
)
r
.
raise_for_status
()
assert
r
.
status_code
>=
200
and
r
.
status_code
<
300
,
f
"
HTTP error
{
r
.
status_code
}
:
{
r
.
reason
}
\n\n
{
r
.
text
}
"
# Also find and delete the associated dns a/aaaa record
endpoint
=
'
record:a
'
if
ip_version
==
4
else
'
record:aaaa
'
r
=
requests
.
get
(
f
'
{
_wapi
(
infoblox_params
)
}
/
{
endpoint
}
'
,
params
=
{
ip_param
:
addr
},
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
verify
=
False
)
dns_data
=
r
.
json
()
assert
len
(
dns_data
)
==
1
,
"
DNS record does not exist.
"
assert
'
_ref
'
in
dns_data
[
0
]
dns_ref
=
dns_data
[
0
][
'
_ref
'
]
r
=
requests
.
delete
(
f
'
{
_wapi
(
infoblox_params
)
}
/
{
dns_ref
}
'
,
auth
=
HTTPBasicAuth
(
infoblox_params
.
username
,
infoblox_params
.
password
),
verify
=
False
)
assert
r
.
status_code
>=
200
and
r
.
status_code
<
300
,
f
"
HTTP error
{
r
.
status_code
}
:
{
r
.
reason
}
\n\n
{
r
.
text
}
"
if
ip_version
==
4
:
if
ip_version
==
4
:
return
V4HostAddress
(
v4
=
addr
)
return
V4HostAddress
(
v4
=
addr
)
...
@@ -287,8 +329,9 @@ if __name__ == '__main__':
...
@@ -287,8 +329,9 @@ if __name__ == '__main__':
print
(
"
4. Delete network
"
)
print
(
"
4. Delete network
"
)
print
(
"
5. Allocate host by IP
"
)
print
(
"
5. Allocate host by IP
"
)
print
(
"
6. Allocate host by network CIDR
"
)
print
(
"
6. Allocate host by network CIDR
"
)
print
(
"
7. Delete host by IP
"
)
print
(
"
7. Allocate host by service type
"
)
print
(
"
8. Exit
"
)
print
(
"
8. Delete host by IP
"
)
print
(
"
9. Exit
"
)
choice
=
input
(
"
Enter your choice:
"
)
choice
=
input
(
"
Enter your choice:
"
)
...
@@ -322,23 +365,32 @@ if __name__ == '__main__':
...
@@ -322,23 +365,32 @@ if __name__ == '__main__':
elif
choice
==
'
5
'
:
elif
choice
==
'
5
'
:
hostname
=
input
(
"
Enter host name:
"
)
hostname
=
input
(
"
Enter host name:
"
)
addr
=
input
(
"
Enter IP address to allocate:
"
)
addr
=
input
(
"
Enter IP address to allocate:
"
)
mac
=
input
(
"
Enter
mac
address (you can leave empty if IPv6):
"
)
mac
=
"
:
"
.
join
([
"
{:02x}
"
.
format
(
random
.
randint
(
0x00
,
0xff
))
for
i
in
range
(
6
)])
#
input("Enter
MAC
address (you can leave empty if IPv6): ")
alloc_ip
=
allocate_host
(
hostname
=
hostname
,
addr
=
addr
,
mac
=
mac
)
alloc_ip
=
allocate_host
(
hostname
=
hostname
,
addr
=
addr
,
mac
=
mac
)
print
(
json
.
dumps
(
str
(
alloc_ip
),
indent
=
2
))
print
(
json
.
dumps
(
str
(
alloc_ip
),
indent
=
2
))
elif
choice
==
'
6
'
:
elif
choice
==
'
6
'
:
hostname
=
input
(
"
Enter host name:
"
)
hostname
=
input
(
"
Enter host name:
"
)
network
=
input
(
"
Enter an existing network to allocate from (in CIDR notation):
"
)
network
=
input
(
"
Enter an existing network to allocate from (in CIDR notation):
"
)
mac
=
input
(
"
Enter
mac
address (you can leave empty if IPv6):
"
)
mac
=
"
:
"
.
join
([
"
{:02x}
"
.
format
(
random
.
randint
(
0x00
,
0xff
))
for
i
in
range
(
6
)])
#
input("Enter
MAC
address (you can leave empty if IPv6): ")
alloc_ip
=
allocate_host
(
hostname
=
hostname
,
network
=
network
,
mac
=
mac
)
alloc_ip
=
allocate_host
(
hostname
=
hostname
,
network
=
network
,
mac
=
mac
)
print
(
json
.
dumps
(
str
(
alloc_ip
),
indent
=
2
))
print
(
json
.
dumps
(
str
(
alloc_ip
),
indent
=
2
))
elif
choice
==
'
7
'
:
elif
choice
==
'
7
'
:
print
(
"
Not implemented.
"
)
continue
hostname
=
input
(
"
Enter host name:
"
)
service_type
=
input
(
"
Enter service type:
"
)
mac
=
"
:
"
.
join
([
"
{:02x}
"
.
format
(
random
.
randint
(
0x00
,
0xff
))
for
i
in
range
(
6
)])
#input("Enter MAC address (you can leave empty if IPv6): ")
alloc_ip
=
allocate_host
(
hostname
=
hostname
,
service_type
=
service_type
,
mac
=
mac
)
print
(
json
.
dumps
(
str
(
alloc_ip
),
indent
=
2
))
elif
choice
==
'
8
'
:
addr
=
input
(
"
Enter IP address of host to delete:
"
)
addr
=
input
(
"
Enter IP address of host to delete:
"
)
deleted_host
=
delete_host_by_ip
(
addr
=
addr
)
deleted_host
=
delete_host_by_ip
(
addr
=
addr
)
print
(
json
.
dumps
(
str
(
deleted_host
),
indent
=
2
))
print
(
json
.
dumps
(
str
(
deleted_host
),
indent
=
2
))
elif
choice
==
'
8
'
:
elif
choice
==
'
9
'
:
print
(
"
Exiting...
"
)
print
(
"
Exiting...
"
)
break
break
...
...
This diff is collapsed.
Click to expand it.
gso/services/ipam.py
+
30
−
11
View file @
5e008e08
import
ipaddress
import
ipaddress
from
pydantic
import
BaseSettings
from
pydantic
import
BaseSettings
from
gso
import
settings
from
gso
import
settings
import
_ipam
class
ServiceNetwork
s
(
BaseSettings
):
class
V4
ServiceNetwork
(
BaseSettings
):
v4
:
ipaddress
.
IPv4Network
v4
:
ipaddress
.
IPv4Network
class
V6ServiceNetwork
(
BaseSettings
):
v6
:
ipaddress
.
IPv6Network
v6
:
ipaddress
.
IPv6Network
class
HostAddresses
(
BaseSettings
):
class
ServiceNetworks
(
BaseSettings
):
v4
:
V4ServiceNetwork
v6
:
V6ServiceNetwork
class
V4HostAddress
(
BaseSettings
):
v4
:
ipaddress
.
IPv4Address
v4
:
ipaddress
.
IPv4Address
v6
:
ipaddress
.
IPv6Address
def
new_service_networks
(
class
V6HostAddress
(
BaseSettings
):
service_params
:
settings
.
ServiceNetworkParams
)
->
ServiceNetworks
:
v6
:
ipaddress
.
IPv6Address
oss
=
settings
.
load_oss_params
()
assert
oss
.
IPAM
.
INFOBLOX
# TODO: load from ipam
class
HostAddresses
(
BaseSettings
):
# cf. https://gitlab.geant.org/goat/gap-jenkins/-/blob/development/service-editor/gap_service_editor/ipam.py#L35-66 # noqa: E501
v4
:
V4HostAddress
v6
:
V6HostAddress
def
new_service_networks
(
service_type
)
->
ServiceNetworks
:
v4_service_network
=
_ipam
.
allocate_service_ipv4_network
(
service_type
=
service_type
)
v6_service_network
=
_ipam
.
allocate_service_ipv6_network
(
service_type
=
service_type
)
return
ServiceNetworks
(
return
ServiceNetworks
(
v4
=
ipaddress
.
IPv4Network
(
'
10.0.0.0/24
'
)
,
v4
=
v4_service_network
,
v6
=
ipaddress
.
IPv6Network
(
'
dead:beef::/120
'
)
)
v6
=
v6_service_network
)
def
new_device_lo_address
()
->
HostAddresses
:
def
new_device_lo_address
()
->
HostAddresses
:
...
@@ -31,3 +46,7 @@ def new_device_lo_address() -> HostAddresses:
...
@@ -31,3 +46,7 @@ def new_device_lo_address() -> HostAddresses:
return
HostAddresses
(
return
HostAddresses
(
v4
=
ipaddress
.
IPv4Address
(
'
10.10.10.10
'
),
v4
=
ipaddress
.
IPv4Address
(
'
10.10.10.10
'
),
v6
=
ipaddress
.
IPv6Address
(
'
fc00:798:aa:1::10
'
))
v6
=
ipaddress
.
IPv6Address
(
'
fc00:798:aa:1::10
'
))
if
__name__
==
'
__main__
'
:
new_service_networks
(
'
TRUNK
'
)
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment