Pushing existing code
This commit is contained in:
parent
57a06cee89
commit
887d2e5a8a
22
README.md
22
README.md
@ -1,2 +1,24 @@
|
||||
# IPAMLite
|
||||
|
||||
## Command Line Operation
|
||||
```
|
||||
IP Address Manager (Lite)
|
||||
Example usage:
|
||||
$ cd IPAMLite
|
||||
$ chmod +x ipam
|
||||
$ ./ipam
|
||||
|
||||
$ curl -X POST -H "Content-type: application/json" -d "{\"ip\" : \"192.168.1.5\", \"subnet\" : \"24\"}" "127.0.0.1:5000/specific_lease"
|
||||
$ curl -X POST -H "Content-type: application/json" -d "{\"network\" : \"192.168.1.0\", \"subnet\" : \"24\"}" "127.0.0.1:5000/sequential_lease"
|
||||
$ curl -X POST -H "Content-type: application/json" -d "{\"ip\" : \"192.168.1.5\", \"subnet\" : \"24\"}" "127.0.0.1:5000/release"
|
||||
$ curl 127.0.0.1:5000/database
|
||||
|
||||
Currently supported API calls:
|
||||
- /specific_lease - HTTP POST, adds a specified IP address to the database
|
||||
- Takes: ip, subnet
|
||||
- /sequential_lease - HTTP POST, adds the next available IP address in the subnet to the database
|
||||
- Takes: network, subnet
|
||||
- /release - HTTP POST, release an IP address from the database
|
||||
- Takes: ip, subnet
|
||||
- /database - HTTP GET, returns the IP address database
|
||||
```
|
130
ipam
Executable file
130
ipam
Executable file
@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import ipaddress
|
||||
import json
|
||||
import os
|
||||
|
||||
from flask import Flask, request
|
||||
|
||||
class IPAMLite(object):
|
||||
def __init__(self, database_file='ipam.json'):
|
||||
self.database_file = database_file
|
||||
self.leased = []
|
||||
|
||||
def database(self):
|
||||
return(json.dumps(self.leased, indent=4))
|
||||
|
||||
def sequential_lease(self, network, subnet):
|
||||
network_exists = False
|
||||
host_addresses = [str(ip) for ip in ipaddress.IPv4Network(f'{network}/{subnet}').hosts()]
|
||||
|
||||
for network_dict in self.leased:
|
||||
if f'{network}/{subnet}' in network_dict.keys():
|
||||
for network_address, leased_addresses in network_dict.items():
|
||||
leaseable_addresses = [ip for ip in host_addresses if ip not in leased_addresses]
|
||||
if len(leaseable_addresses) >= 1:
|
||||
next_available_lease = leaseable_addresses[0]
|
||||
leased_addresses.append(next_available_lease)
|
||||
network_exists = True
|
||||
break
|
||||
else:
|
||||
return f'\U0001F916 No address space left in: {network}/{subnet}\n'
|
||||
|
||||
if not network_exists:
|
||||
next_available_lease = host_addresses[0]
|
||||
self.leased.append({str(f'{network}/{subnet}'): [next_available_lease]})
|
||||
|
||||
self.save_database()
|
||||
return f'\U0001F916 Lease added: {next_available_lease}/{subnet}\n'
|
||||
|
||||
def specific_lease(self, ip, subnet):
|
||||
network_exists = False
|
||||
network_address = ipaddress.ip_interface(f'{ip}/{subnet}').network
|
||||
|
||||
for network_dict in self.leased:
|
||||
for network, leased_addresses in network_dict.items():
|
||||
if ip in leased_addresses:
|
||||
return f'\U0001F916 Lease already exists: {ip}/{subnet}\n'
|
||||
if str(network) == str(network_address):
|
||||
leased_addresses.append(ip)
|
||||
network_exists = True
|
||||
|
||||
if not network_exists:
|
||||
self.leased.append({str(network_address): [ip]})
|
||||
|
||||
self.save_database()
|
||||
return f'\U0001F916 Lease added: {ip}/{subnet}\n'
|
||||
|
||||
def release(self, ip, subnet):
|
||||
for index in range(len(self.leased)):
|
||||
for network, leased_addresses in self.leased[index].items():
|
||||
if ip in leased_addresses and len(leased_addresses) < 2:
|
||||
del self.leased[index]
|
||||
self.save_database()
|
||||
return f'\U0001F916 Lease removed: {ip}/{subnet}\n'
|
||||
break
|
||||
elif ip in leased_addresses and len(leased_addresses) > 1:
|
||||
leased_addresses.remove(ip)
|
||||
self.save_database()
|
||||
return f'\U0001F916 Lease removed: {ip}/{subnet}\n'
|
||||
break
|
||||
|
||||
return f'\U0001F916 Nothing to release for: {ip}/{subnet}\n'
|
||||
|
||||
def save_database(self):
|
||||
with open(self.database_file, 'w') as ipam_file:
|
||||
json.dump(self.leased, ipam_file, indent=4)
|
||||
|
||||
def load_database(self):
|
||||
if os.path.exists(self.database_file):
|
||||
with open(self.database_file, 'r') as ipam_file:
|
||||
db = json.load(ipam_file)
|
||||
|
||||
for lease in db:
|
||||
self.leased.append(lease)
|
||||
|
||||
print(f'\U0001F916 Database file "{self.database_file}" loaded successfully')
|
||||
else:
|
||||
print(f'\U0001F916 Cannot load database file "{self.database_file}"')
|
||||
|
||||
IPAM = IPAMLite()
|
||||
IPAM.load_database()
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/database', methods=['GET'])
|
||||
def get_database():
|
||||
return IPAM.database()
|
||||
|
||||
@app.route('/sequential_lease', methods=['POST'])
|
||||
def handle_sequential_lease():
|
||||
if request.is_json:
|
||||
data = request.json
|
||||
lease_response = IPAM.sequential_lease(data['network'], data['subnet'])
|
||||
|
||||
return f'{lease_response}'
|
||||
else:
|
||||
return 'Data type not supported, supported data types: JSON\n'
|
||||
|
||||
@app.route('/specific_lease', methods=['POST'])
|
||||
def handle_specific_lease():
|
||||
if request.is_json:
|
||||
data = request.json
|
||||
lease_response = IPAM.specific_lease(data['ip'], data['subnet'])
|
||||
|
||||
return f'{lease_response}'
|
||||
else:
|
||||
return 'Data type not supported, supported data types: JSON\n'
|
||||
|
||||
@app.route('/release', methods=['POST'])
|
||||
def handle_release():
|
||||
if request.is_json:
|
||||
data = request.json
|
||||
release_response = IPAM.release(data['ip'], data['subnet'])
|
||||
|
||||
return f'{release_response}'
|
||||
else:
|
||||
return 'Data type not supported, supported data types: JSON\n'
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug = True)
|
Loading…
Reference in New Issue
Block a user