Skip to content

Commit 6a5950a

Browse files
feat: add model and endpoint for DHCPRelay #121
1 parent 1c90611 commit 6a5950a

2 files changed

Lines changed: 131 additions & 0 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace RESTAPI\Endpoints;
4+
5+
require_once 'RESTAPI/autoloader.inc';
6+
7+
use RESTAPI\Core\Endpoint;
8+
9+
/**
10+
* Defines an Endpoint for interacting with the DHCPRelay Model object at /api/v2/services/dhcp_relay.
11+
*/
12+
class ServicesDHCPRelayEndpoint extends Endpoint {
13+
public function __construct() {
14+
# Set Endpoint attributes
15+
$this->url = '/api/v2/services/dhcp_relay';
16+
$this->model_name = 'DHCPRelay';
17+
$this->request_method_options = ['GET', 'PATCH'];
18+
19+
# Construct the parent Endpoint object
20+
parent::__construct();
21+
}
22+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
namespace RESTAPI\Models;
4+
5+
use RESTAPI\Core\Model;
6+
use RESTAPI\Fields\BooleanField;
7+
use RESTAPI\Fields\ForeignModelField;
8+
use RESTAPI\Fields\InterfaceField;
9+
use RESTAPI\Fields\StringField;
10+
use RESTAPI\Responses\ConflictError;
11+
use RESTAPI\Validators\IPAddressValidator;
12+
13+
/**
14+
* Defines a Model for interacting with the DHCP relay configuration.
15+
*/
16+
class DHCPRelay extends Model {
17+
public BooleanField $enable;
18+
public InterfaceField $interface;
19+
public BooleanField $agentoption;
20+
public ForeignModelField $carpstatusvip;
21+
public StringField $server;
22+
23+
public function __construct(mixed $id = null, mixed $parent_id = null, mixed $data = [], mixed ...$options) {
24+
# Set model attributes
25+
$this->config_path = 'dhrelay';
26+
$this->many = false;
27+
$this->always_apply = true;
28+
29+
# Set model fields
30+
$this->enable = new BooleanField(default: false, help_text: 'Enables or disables the DHCP relay.');
31+
$this->interface = new InterfaceField(
32+
default: [],
33+
many: true,
34+
help_text: 'The downstream interfaces to listen on for DHCP requests.',
35+
);
36+
$this->agentoption = new BooleanField(
37+
default: false,
38+
help_text: 'Enables or disables appending the circuit ID (interface number) and the agent ID to the ' .
39+
'DHCP request.',
40+
);
41+
$this->carpstatusvip = new ForeignModelField(
42+
model_name: 'VirtualIP',
43+
model_field: 'uniqid',
44+
allowed_keywords: ['none'],
45+
default: 'none',
46+
help_text: 'DHCP Relay will be stopped when the chosen VIP is in BACKUP status, and started ' .
47+
'in MASTER status.',
48+
);
49+
$this->server = new StringField(
50+
required: true,
51+
many: true,
52+
many_minimum: 1,
53+
validators: [new IPAddressValidator(allow_ipv6: false)],
54+
help_text: 'The IPv4 addresses of the DHCP server to relay requests to.',
55+
);
56+
57+
parent::__construct($id, $parent_id, $data, ...$options);
58+
}
59+
60+
/**
61+
* Provide extra validation to the 'enable' field.
62+
* @param bool $enable The value to be validated.
63+
* @return bool The validated value.
64+
* @throws ConflictError If the DHCP relay is being enabled but a DHCP Server is running.
65+
*/
66+
public function validate_enable(bool $enable): bool {
67+
if ($enable and DHCPServer::query(enable: true)->exists()) {
68+
throw new ConflictError(
69+
message: 'DHCP Relay cannot be enabled while DHCP Server is enabled on any interface.',
70+
response_id: 'DHCP_RELAY_CANNOT_BE_ENABLED_WHILE_DHCP_SERVER_IS_ENABLED',
71+
);
72+
}
73+
74+
return $enable;
75+
}
76+
77+
/**
78+
* Override the default 'to_internal()' method to ensure the carpstatusvip field is prefixed with '_vip'.
79+
*/
80+
public function to_internal(): array|string {
81+
$internal_data = parent::to_internal();
82+
83+
if ($this->carpstatusvip->value !== 'none') {
84+
$internal_data['carpstatusvip'] = "_vip{$internal_data['carpstatusvip']}";
85+
}
86+
87+
return $internal_data;
88+
}
89+
90+
/**
91+
* Add custom logic for when the 'carpstatusvip' field is being set from its internal value. This is used to
92+
* remove the _vip prefix from the value so the framework can locate it's related VirtualIP model.
93+
*/
94+
public function from_internal_carpstatusvip(string $value): string {
95+
if (str_starts_with($value, '_vip')) {
96+
return substr($value, 4);
97+
}
98+
99+
return $value;
100+
}
101+
102+
/**
103+
* Apply changes to the DHCP relay
104+
*/
105+
public function apply(): void {
106+
services_dhcrelay_configure();
107+
filter_configure();
108+
}
109+
}

0 commit comments

Comments
 (0)