Skip to content
Merged

Dhcp #67

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fc348c1
Add initial work for ip control module
jhughesoti Jun 16, 2023
a2bbe01
Implement ip control module with additional cleanup methods
jhughesoti Jun 16, 2023
016472b
Update link check to not use error stream
jhughesoti Jun 19, 2023
2d7b076
Add error checking around container network configurations
jhughesoti Jun 19, 2023
b71ba1d
Add network cleanup for namespaces and links
jhughesoti Jun 19, 2023
386f41f
formatting
jhughesoti Jun 19, 2023
31572e5
initial work on adding grpc functions for dhcp tests
jhughesoti Jun 26, 2023
b965bb1
rework code to allow for better usage and unit testing
jhughesoti Jun 28, 2023
9a74d65
working poc for test containers and grpc client to dhcp-1
jhughesoti Jun 29, 2023
d442421
Move grpc client code into base image
jhughesoti Jun 29, 2023
ec7cc65
Move grpc proto builds outside of dockerfile into module startup script
jhughesoti Jun 29, 2023
e3102ca
Setup pythonpath var in test module base startup process
jhughesoti Jun 30, 2023
ed6257f
pylinting and logging updates
jhughesoti Jun 30, 2023
c53263b
Add python path resolving to network modules
jhughesoti Jun 30, 2023
62d46b7
Change lease resolving method to fix pylint issue
jhughesoti Jun 30, 2023
227ad58
cleanup unit tests
jhughesoti Jul 3, 2023
976f116
cleanup unit tests
jhughesoti Jul 3, 2023
8a2526b
Add grpc updates to dhcp2 module
jhughesoti Jul 3, 2023
0fd5a8d
Add grpc updates to dhcp2 module
jhughesoti Jul 3, 2023
22658d5
merge dev
jhughesoti Jul 3, 2023
1b3f13f
fix line endings
jhughesoti Jul 3, 2023
d4e3e91
misc cleanup
jhughesoti Jul 3, 2023
51da71f
Move isc-dhcp-server and radvd to services
jhughesoti Jul 6, 2023
48b9f71
Add grpc methods to interact with dhcp_server module
jhughesoti Jul 6, 2023
020ca9e
Add updates to dhcp2 module
jhughesoti Jul 6, 2023
87c5e54
merge dev
jhughesoti Jul 6, 2023
896daa2
Add license headers
jhughesoti Jul 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions modules/network/dhcp-1/bin/radvd-service
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

RA_PID_FILE=/var/run/radvd/radvd.pid
RA_LOG_FILE=/runtime/network/dhcp1-radvd.log

stop_radvd(){
# Directly kill by PID file reference
if [ -f "$RA_PID_FILE" ]; then
kill -9 $(cat $RA_PID_FILE) || true
rm -f $RA_PID_FILE
fi
}

start_radvd(){
/usr/sbin/radvd -m logfile -l $RA_LOG_FILE -p $RA_PID_FILE
}

case "$1" in
start)
start_radvd
;;
stop)
stop_radvd
;;
restart)
stop_radvd
sleep 1
start_radvd
;;
status)
if [ -f "$RA_PID_FILE" ]; then
echo "radvd service is running."
else
echo "radvd service is not running."
fi
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
;;
esac
56 changes: 8 additions & 48 deletions modules/network/dhcp-1/bin/start_network_service
Original file line number Diff line number Diff line change
Expand Up @@ -29,63 +29,23 @@ sysctl -p
# Create leases file if needed
touch /var/lib/dhcp/dhcpd.leases

#Create directory for radvd
# Create directory for radvd
mkdir /var/run/radvd

#Create and set permissions on the log files
# Create and set permissions on the log files
touch $DHCP_LOG_FILE
touch $RA_LOG_FILE
chown $HOST_USER $DHCP_LOG_FILE
chown $HOST_USER $RA_LOG_FILE


#Move the config files to the correct location
# Move the config files to the correct location
cp /testrun/conf/isc-dhcp-server /etc/default/
cp /testrun/conf/dhcpd.conf /etc/dhcp/dhcpd.conf
cp /testrun/conf/radvd.conf /etc/radvd.conf

# Restart dhcp server when config changes
while true; do
# Move the radvd-sevice file to the correct location
cp /testrun/bin/radvd-service /usr/local/bin/

new_checksum=$(md5sum $CONFIG_FILE)

if [ "$checksum" == "$new_checksum" ]; then
sleep 2
continue
fi

echo Config changed. Restarting dhcp server at $(date)..

if [ -f $DHCP_PID_FILE ]; then
kill -9 $(cat $DHCP_PID_FILE) || true
rm -f $DHCP_PID_FILE
fi

if [ -f $RA_PID_FILE ]; then
kill -9 $(cat $RA_PID_FILE) || true
rm -f $RA_PID_FILE
fi

checksum=$new_checksum

echo Starting isc-dhcp-server at $(date)

radvd -m logfile -l $RA_LOG_FILE -p $RA_PID_FILE
dhcpd -d &> $DHCP_LOG_FILE &

while [ ! -f $DHCP_PID_FILE ]; do
echo Waiting for $DHCP_PID_FILE...
sleep 2
done

echo $DHCP_PID_FILE now available

while [ ! -f $RA_PID_FILE ]; do
echo Waiting for $RA_PID_FILE...
sleep 2
done

echo $RA_PID_FILE now available

echo Server now stable

done
# Start the DHCP Server
python3 -u /testrun/python/src/grpc_server/dhcp_server.py
4 changes: 4 additions & 0 deletions modules/network/dhcp-1/conf/isc-dhcp-server
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4="veth0"
#INTERFACESv6="veth0"
2 changes: 1 addition & 1 deletion modules/network/dhcp-1/dhcp-1.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ RUN apt-get install -y wget
RUN wget http://standards-oui.ieee.org/oui.txt -P /usr/local/etc/

# Install dhcp server
RUN apt-get install -y isc-dhcp-server radvd
RUN apt-get install -y isc-dhcp-server radvd systemd

# Copy over all configuration files
COPY $MODULE_DIR/conf /testrun/conf
Expand Down
130 changes: 130 additions & 0 deletions modules/network/dhcp-1/python/src/grpc_server/dhcp_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Contains all the necessary classes to maintain the
DHCP server"""
import time
from common import logger
from common import util
from dhcp_config import DHCPConfig
from radvd_server import RADVDServer

CONFIG_FILE = '/etc/dhcp/dhcpd.conf'
LOG_NAME = 'dhcp_server'
LOGGER = None


class DHCPServer:
"""Represents the DHCP Server"""

def __init__(self):
global LOGGER
LOGGER = logger.get_logger(LOG_NAME, 'dhcp-1')
self.dhcp_config = DHCPConfig()
self.radvd = RADVDServer()
self.dhcp_config.resolve_config()

def restart(self):
LOGGER.info("Restarting DHCP Server")
isc_started = util.run_command("service isc-dhcp-server restart", False)
radvd_started = self.radvd.restart()
started = isc_started and radvd_started
LOGGER.info("DHCP Restarted: " + str(started))
return started

def start(self):
LOGGER.info("Starting DHCP Server")
isc_started = util.run_command("service isc-dhcp-server start", False)
radvd_started = self.radvd.start()
started = isc_started and radvd_started
LOGGER.info("DHCP Started: " + str(started))
return started

def stop(self):
LOGGER.info("Stopping DHCP Server")
isc_stopped = util.run_command("service isc-dhcp-server stop", False)
radvd_stopped = self.radvd.stop()
stopped = isc_stopped and radvd_stopped
LOGGER.info("DHCP Stopped: " + str(stopped))
return stopped

def is_running(self):
LOGGER.info("Checking DHCP Status")
response = util.run_command("service isc-dhcp-server status")
isc_running = response[0] == 'Status of ISC DHCPv4 server: dhcpd is running.'
radvd_running = self.radvd.is_running()
running = isc_running and radvd_running
LOGGER.info("DHCP Status: " + str(running))
return running

def boot(self):
LOGGER.info("Booting DHCP Server")
isc_booted = False
radvd_booted = False
if self.is_running():
LOGGER.info("Stopping isc-dhcp-server")
stopped = self.stop()
LOGGER.info("isc-dhcp-server stopped: " + str(stopped))

if self.radvd.is_running():
LOGGER.info("Stopping RADVD")
stopped = self.radvd.stop()
LOGGER.info("radvd stopped: " + str(stopped))

LOGGER.info("Starting isc-dhcp-server")
if self.start():
isc_booted = False
# Scan for 5 seconds if not yet ready
for i in range(5):
time.sleep(1)
isc_booted = self.is_running()
if isc_booted:
break;
LOGGER.info("isc-dhcp-server started: " + str(isc_booted))

LOGGER.info("Starting RADVD")
if self.radvd.start():
radvd_booted = False
# Scan for 5 seconds if not yet ready
for i in range(5):
time.sleep(1)
radvd_booted = self.radvd.is_running()
if radvd_booted:
break;
LOGGER.info("RADVD started: " + str(radvd_booted))



return isc_booted and radvd_booted

def run():
dhcp_server = DHCPServer()
booted = dhcp_server.boot()

if not booted:
LOGGER.error('DHCP Server Failed to boot. Exiting')
sys.exit(1)

config = str(dhcp_server.dhcp_config)
while True:
dhcp_server.dhcp_config.resolve_config()
new_config = str(dhcp_server.dhcp_config)
if config != new_config:
LOGGER.info("DHCP Config Changed")
config = new_config
success = dhcp_server.restart()
success = dhcp_server.radvd.restart()
time.sleep(1)

if __name__ == '__main__':
run()
43 changes: 40 additions & 3 deletions modules/network/dhcp-1/python/src/grpc_server/network_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import proto.grpc_pb2_grpc as pb2_grpc
import proto.grpc_pb2 as pb2

from dhcp_server import DHCPServer
from dhcp_config import DHCPConfig
from dhcp_leases import DHCPLeases

Expand All @@ -28,6 +29,7 @@ class NetworkService(pb2_grpc.NetworkModule):
"""gRPC endpoints for the DHCP Server"""

def __init__(self):
self._dhcp_server = DHCPServer()
self._dhcp_config = None
self.dhcp_leases = DHCPLeases()
global LOGGER
Expand All @@ -39,6 +41,42 @@ def _get_dhcp_config(self):
self._dhcp_config.resolve_config()
return self._dhcp_config

def RestartDHCPServer(self, request, context): # pylint: disable=W0613
LOGGER.info('Restarting DHCP server')
try:
started = self._dhcp_server.restart()
LOGGER.info('DHCP server restarted: ' + (str(started)))
return pb2.Response(code=200, message='{}')
except Exception as e: # pylint: disable=W0718
fail_message = 'Failed to restart DHCP server: ' + str(e)
LOGGER.error(fail_message)
LOGGER.error(traceback.format_exc())
return pb2.Response(code=500, message=fail_message)

def StartDHCPServer(self, request, context): # pylint: disable=W0613
LOGGER.info('Starting DHCP server')
try:
started = self._dhcp_server.start()
LOGGER.info('DHCP server started: ' + (str(started)))
return pb2.Response(code=200, message='{}')
except Exception as e: # pylint: disable=W0718
fail_message = 'Failed to start DHCP server: ' + str(e)
LOGGER.error(fail_message)
LOGGER.error(traceback.format_exc())
return pb2.Response(code=500, message=fail_message)

def StopDHCPServer(self, request, context): # pylint: disable=W0613
LOGGER.info('Stopping DHCP server')
try:
stopped = self._dhcp_server.stop()
LOGGER.info('DHCP server stopped: ' + (str(stopped)))
return pb2.Response(code=200, message='{}')
except Exception as e: # pylint: disable=W0718
fail_message = 'Failed to stop DHCP server: ' + str(e)
LOGGER.error(fail_message)
LOGGER.error(traceback.format_exc())
return pb2.Response(code=500, message=fail_message)

def AddReservedLease(self, request, context): # pylint: disable=W0613
LOGGER.info('Add reserved lease called')
try:
Expand Down Expand Up @@ -151,7 +189,6 @@ def GetStatus(self, request, context): # pylint: disable=W0613
"""
Return the current status of the network module
"""
# ToDo: Figure out how to resolve the current DHCP status
dhcp_status = True
dhcp_status = self._dhcp_server.is_running()
message = str({'dhcpStatus': dhcp_status})
return pb2.Response(code=200, message=message)
return pb2.Response(code=200, message=message)
16 changes: 14 additions & 2 deletions modules/network/dhcp-1/python/src/grpc_server/proto/grpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ syntax = "proto3";

service NetworkModule {

rpc RestartDHCPServer(RestartDHCPServerRequest) returns (Response) {};

rpc StartDHCPServer(StartDHCPServerRequest) returns (Response) {};

rpc StopDHCPServer(StopDHCPServerRequest) returns (Response) {};

rpc AddReservedLease(AddReservedLeaseRequest) returns (Response) {};

rpc DeleteReservedLease(DeleteReservedLeaseRequest) returns (Response) {};
Expand Down Expand Up @@ -29,6 +35,12 @@ message DeleteReservedLeaseRequest {
string hw_addr = 1;
}

message RestartDHCPServerRequest {}

message StartDHCPServerRequest {}

message StopDHCPServerRequest {}

message DisableFailoverRequest {}

message EnableFailoverRequest {}
Expand All @@ -53,7 +65,7 @@ message Response {
}

message DHCPRange {
int32 code = 1;
int32 code = 1;
string start = 2;
string end = 3;
}
}
Loading