forked from aibor/marmoset
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from virtapi/feat-isc-dhcp
Feat isc dhcp
- Loading branch information
Showing
11 changed files
with
581 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
from . import config, cli | ||
from marmoset import config | ||
from marmoset import cli | ||
from marmoset import validation | ||
|
||
def run(config_file = None): | ||
|
||
def run(config_file=None): | ||
cfg = config.load(config_file) | ||
cli.parse(cfg) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
from . import config, webserver | ||
|
||
app = webserver.app(config.load()) | ||
config = config.load() | ||
|
||
app = webserver.app(config) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .dhcp_config import DhcpConfig | ||
from .isc_dhcp_ldap_config import ISCDhcpLdapConfig |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
from .isc_dhcp_ldap_config import ISCDhcpLdapConfig | ||
from marmoset import validation | ||
from marmoset import config as config_reader | ||
|
||
config = config_reader.load() | ||
|
||
|
||
class DhcpConfig: | ||
def __init__(self, mac, ip_address, gateway=None, networkmask=None): | ||
self.additional_statements = {} | ||
|
||
self.mac = None | ||
self.ip_address = None | ||
self.gateway = None | ||
self.networkmask = None | ||
self.dhcp_hostname = None | ||
|
||
self.set_settings(True, mac, ip_address, gateway, networkmask) | ||
|
||
def set_settings(self, allow_none_value_for_not_required_parameter=False, mac=None, ip_address=None, | ||
gateway=None, networkmask=None): | ||
self.mac = mac | ||
|
||
if gateway is not None or allow_none_value_for_not_required_parameter: | ||
self.gateway = gateway | ||
|
||
if networkmask is not None or allow_none_value_for_not_required_parameter: | ||
self.networkmask = networkmask | ||
|
||
if validation.is_cidr(ip_address): | ||
self.ip_address = validation.get_ip_from_cidr(ip_address) | ||
|
||
if self.networkmask is None: | ||
self.networkmask = validation.get_nm_from_cidr(ip_address) | ||
|
||
if self.gateway is None: | ||
self.gateway = validation.get_gw_from_cidr(ip_address) | ||
else: | ||
self.ip_address = ip_address | ||
|
||
self.dhcp_hostname = config['Common'].get('FQDN') | ||
|
||
def add_additional_statement(self, key, value): | ||
self.additional_statements[key] = value | ||
|
||
def create_isc_ldap(self): | ||
isc_dhcp_config = ISCDhcpLdapConfig(self) | ||
isc_dhcp_config.save() | ||
|
||
def remove_by_ipv4(self): | ||
return ISCDhcpLdapConfig.remove_by_ipv4(self.ip_address) > 0 | ||
|
||
def remove_by_mac(self): | ||
return ISCDhcpLdapConfig.remove_by_mac(self.mac) > 0 | ||
|
||
def remove_all(self): | ||
ipv4_removed_count = ISCDhcpLdapConfig.remove_by_ipv4(self.ip_address) | ||
mac_removed_count = ISCDhcpLdapConfig.remove_by_mac(self.mac) | ||
|
||
return (ipv4_removed_count + mac_removed_count) > 0 | ||
|
||
@staticmethod | ||
def all(): | ||
return ISCDhcpLdapConfig.all() | ||
|
||
@staticmethod | ||
def get_by_ip(ip_address): | ||
return ISCDhcpLdapConfig.get_by_ip(ip_address) | ||
|
||
@staticmethod | ||
def get_by_mac(mac): | ||
return ISCDhcpLdapConfig.get_by_mac(mac) | ||
|
||
@staticmethod | ||
def exists_ipv4(ip_address): | ||
return ISCDhcpLdapConfig.get_by_ip(ip_address) is not None | ||
|
||
@staticmethod | ||
def exists_mac(mac_address): | ||
return ISCDhcpLdapConfig.get_by_mac(mac_address) is not None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
from ldap3 import Server, Connection, ALL, SUBTREE, BASE, ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES | ||
from datetime import datetime | ||
from marmoset import config as config_reader | ||
|
||
import re | ||
|
||
config = config_reader.load() | ||
|
||
|
||
class ISCDhcpLdapConfig: | ||
def __init__(self, dhcp_config): | ||
self.dhcp_config = dhcp_config | ||
|
||
@staticmethod | ||
def __get_server_connection(): | ||
server = Server(config['DHCPConfig'].get('ldap_server'), | ||
port=int(config['DHCPConfig'].get('ldap_port')), | ||
get_info=ALL) | ||
|
||
conn = Connection(server, | ||
config['DHCPConfig'].get('ldap_bind_dn'), | ||
config['DHCPConfig'].get('ldap_passwort'), | ||
auto_bind=True) | ||
|
||
return conn | ||
|
||
def save(self): | ||
conn = self.__get_server_connection() | ||
|
||
dhcpStatements = ["fixed-address %s;" % self.dhcp_config.ip_address, | ||
"option subnet-mask %s;" % self.dhcp_config.networkmask, | ||
"option routers %s;" % self.dhcp_config.gateway] | ||
|
||
for additional_statement in self.dhcp_config.additional_statements: | ||
dhcpStatements.append("%s %s;" % (additional_statement, | ||
self.dhcp_config.additional_statements[additional_statement])) | ||
|
||
entry_attributes = {'dhcpHWAddress': "ethernet %s" % self.dhcp_config.mac, | ||
'dhcpStatements': dhcpStatements, | ||
'dhcpComments': "date=%s dhcp-hostname=%s" % (datetime.now().strftime("%Y%m%d_%H%M%S"), | ||
self.dhcp_config.dhcp_hostname)} | ||
|
||
conn.add("cn=%s,%s" % (self.dhcp_config.ip_address, config['DHCPConfig'].get('ldap_client_base_dn')), | ||
'dhcpHost', | ||
entry_attributes) | ||
|
||
@staticmethod | ||
def all(): | ||
conn = ISCDhcpLdapConfig.__get_server_connection() | ||
|
||
entry_generator = conn.extend.standard.paged_search(search_base=config['DHCPConfig'].get('ldap_client_base_dn'), | ||
search_filter='(objectClass=dhcpHost)', | ||
search_scope=SUBTREE, | ||
attributes=['cn'], | ||
paged_size=5, | ||
generator=True) | ||
result = [] | ||
for entry in entry_generator: | ||
result.append(ISCDhcpLdapConfig.get_by_ip(entry['attributes']['cn'][0])) | ||
|
||
return result | ||
|
||
@staticmethod | ||
def __get_dn_by_ipv4(ip_address, multi=False): | ||
conn = ISCDhcpLdapConfig.__get_server_connection() | ||
conn.search(search_base=config['DHCPConfig'].get('ldap_client_base_dn'), | ||
search_filter='(cn=%s)' % ip_address, | ||
search_scope=SUBTREE, | ||
paged_size=5, | ||
attributes=[ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES]) | ||
|
||
entries = conn.response | ||
|
||
if entries is None or len(entries) == 0: | ||
if multi: | ||
return [] | ||
return None | ||
|
||
if multi: | ||
dn_list = [] | ||
for entry in entries: | ||
dn_list.append(entry['dn']) | ||
|
||
return dn_list | ||
|
||
return entries[0]['dn'] | ||
|
||
@staticmethod | ||
def __get_dn_by_mac(mac_address, multi=False): | ||
conn = ISCDhcpLdapConfig.__get_server_connection() | ||
conn.search(search_base=config['DHCPConfig'].get('ldap_client_base_dn'), | ||
search_filter='(dhcpHWAddress=ethernet %s)' % mac_address, | ||
search_scope=SUBTREE, | ||
paged_size=5, | ||
attributes=[ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES]) | ||
|
||
entries = conn.response | ||
|
||
if entries is None or len(entries) == 0: | ||
if multi: | ||
return [] | ||
return None | ||
|
||
if multi: | ||
dn_list = [] | ||
for entry in entries: | ||
dn_list.append(entry['dn']) | ||
|
||
return dn_list | ||
|
||
return entries[0]['dn'] | ||
|
||
@staticmethod | ||
def __get_dhcp_config(dn): | ||
from marmoset.dhcp import DhcpConfig | ||
|
||
conn = ISCDhcpLdapConfig.__get_server_connection() | ||
conn.search(search_base=dn, | ||
search_filter='(objectClass=dhcpHost)', | ||
search_scope=SUBTREE, | ||
paged_size=5, | ||
attributes=[ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES]) | ||
|
||
entries = conn.response | ||
|
||
if len(entries) == 0: | ||
return None | ||
|
||
mac_option = str(entries[0]['attributes']['dhcpHWAddress']) | ||
|
||
regex_gateway = 'option routers\s+([0-9]+.[0-9]+.[0-9]+.[0-9]+)' | ||
regex_networkmask = 'option subnet-mask\s+([0-9]+.[0-9]+.[0-9]+.[0-9]+)' | ||
|
||
mac = re.search('(([0-9a-f]{2}:){5}[0-9a-f]{2})', mac_option).group(0) | ||
ip = entries[0]['attributes']['cn'][0] | ||
|
||
gateway = None | ||
networkmask = None | ||
|
||
for dhcpStatement in entries[0]['attributes']['dhcpStatements']: | ||
if re.match(regex_gateway, dhcpStatement): | ||
gateway = re.search(regex_gateway, dhcpStatement).group(1) | ||
|
||
if re.match(regex_networkmask, dhcpStatement): | ||
networkmask = re.search(regex_networkmask, dhcpStatement).group(1) | ||
|
||
dhcp_config = DhcpConfig(mac, ip, gateway, networkmask) | ||
|
||
additional_statements_str = config['DHCPConfig'].get('additional_statements') | ||
additional_statements = additional_statements_str.split(',') | ||
|
||
for ldap_additional_statement in entries[0]['attributes']['dhcpStatements']: | ||
for additional_statement in additional_statements: | ||
regex_additional_statement = '%s\s+(.*);' % additional_statement | ||
|
||
if re.match(regex_additional_statement, ldap_additional_statement): | ||
value = re.search(regex_additional_statement, ldap_additional_statement).group(1) | ||
dhcp_config.add_additional_statement(additional_statement, value) | ||
|
||
return dhcp_config | ||
|
||
@staticmethod | ||
def get_by_ip(ip_address): | ||
dn = ISCDhcpLdapConfig.__get_dn_by_ipv4(ip_address) | ||
|
||
if dn is None: | ||
return None | ||
|
||
return ISCDhcpLdapConfig.__get_dhcp_config(dn) | ||
|
||
@staticmethod | ||
def get_by_mac(mac_address): | ||
dn = ISCDhcpLdapConfig.__get_dn_by_mac(mac_address) | ||
|
||
if dn is None: | ||
return None | ||
|
||
return ISCDhcpLdapConfig.__get_dhcp_config(dn) | ||
|
||
@staticmethod | ||
def remove_by_ipv4(ipv4): | ||
dn_list = ISCDhcpLdapConfig.__get_dn_by_ipv4(ipv4, multi=True) | ||
|
||
for dn in dn_list: | ||
conn = ISCDhcpLdapConfig.__get_server_connection() | ||
conn.delete(dn) | ||
conn.unbind() | ||
|
||
return len(dn_list) | ||
|
||
@staticmethod | ||
def remove_by_mac(mac): | ||
dn_list = ISCDhcpLdapConfig.__get_dn_by_mac(mac, multi=True) | ||
|
||
for dn in dn_list: | ||
conn = ISCDhcpLdapConfig.__get_server_connection() | ||
conn.delete(dn) | ||
conn.unbind() | ||
|
||
return len(dn_list) |
Oops, something went wrong.