summaryrefslogtreecommitdiff
path: root/src/PVE/Network/SDN/VnetPlugin.pm
blob: 035aaca8504feb190375428b652c99372af7c843 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package PVE::Network::SDN::VnetPlugin;

use strict;
use warnings;

use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
use PVE::Exception qw(raise raise_param_exc);
use PVE::JSONSchema qw(get_standard_option);

use PVE::SectionConfig;
use base qw(PVE::SectionConfig);

PVE::Cluster::cfs_register_file(
    'sdn/vnets.cfg',
    sub { __PACKAGE__->parse_config(@_); },
    sub { __PACKAGE__->write_config(@_); },
);

PVE::JSONSchema::register_standard_option(
    'pve-sdn-vnet-id',
    {
        description => "The SDN vnet object identifier.",
        type => 'string',
        format => 'pve-sdn-vnet-id',
    },
);

PVE::JSONSchema::register_format('pve-sdn-vnet-id', \&parse_sdn_vnet_id);

sub parse_sdn_vnet_id {
    my ($id, $noerr) = @_;

    if ($id !~ m/^[a-z][a-z0-9]*[a-z0-9]$/i) {
        return undef if $noerr;
        die "vnet ID '$id' contains illegal characters\n";
    }
    die "vnet ID '$id' can't be more length than 8 characters\n" if length($id) > 8;
    return $id;
}

my $defaultData = {

    propertyList => {
        vnet => get_standard_option(
            'pve-sdn-vnet-id',
            { completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnet },
        ),
    },
};

sub type {
    return 'vnet';
}

sub private {
    return $defaultData;
}

sub properties {
    return {
        zone => {
            type => 'string',
            description => "zone id",
        },
        type => {
            description => "Type",
            optional => 1,
        },
        tag => {
            type => 'integer',
            description => "vlan or vxlan id",
        },
        vlanaware => {
            type => 'boolean',
            description => 'Allow vm VLANs to pass through this vnet.',
        },
        alias => {
            type => 'string',
            description => "alias name of the vnet",
            pattern => qr/[\(\)-_.\w\d\s]{0,256}/i,
            maxLength => 256,
            optional => 1,
        },
        'isolate-ports' => {
            type => 'boolean',
            description => "If true, sets the isolated property for all members of this VNet",
        },
    };
}

sub options {
    return {
        zone => { optional => 0 },
        tag => { optional => 1 },
        alias => { optional => 1 },
        vlanaware => { optional => 1 },
        'isolate-ports' => { optional => 1 },
    };
}

sub on_delete_hook {
    my ($class, $vnetid, $vnet_cfg) = @_;

    #verify if subnets are associated
    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
    raise_param_exc({ vnet => "Can't delete vnet if subnets exists" }) if $subnets;
}

sub on_update_hook {
    my ($class, $vnetid, $vnet_cfg) = @_;

    my $vnet = $vnet_cfg->{ids}->{$vnetid};
    my $tag = $vnet->{tag};
    my $vlanaware = $vnet->{vlanaware};

    #don't allow vlanaware change if subnets are defined
    if ($vnet->{vlanaware}) {
        my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
        raise_param_exc({ vlanaware => "vlanaware vnet is not compatible with subnets" })
            if $subnets;
    }
}

1;