vfs: drop lseek stat-open checks
[Samba.git] / python / samba / subnets.py
blob986274fe661d9dbfb0ada6a053fa4d730018d1d0
1 # Add/remove subnets to sites.
3 # Copyright (C) Catalyst.Net Ltd 2015
4 # Copyright Matthieu Patou <mat@matws.net> 2011
6 # Catalyst.Net's contribution was written by Douglas Bagnall
7 # <douglas.bagnall@catalyst.net.nz>.
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 import ldb
24 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, LdbError
25 from . sites import SiteNotFoundException
28 class SubnetException(Exception):
29 """Base element for Subnet errors"""
30 pass
33 class SubnetNotFound(SubnetException):
34 """The subnet requested does not exist."""
35 pass
38 class SubnetAlreadyExists(SubnetException):
39 """The subnet being added already exists."""
40 pass
43 class SubnetInvalid(SubnetException):
44 """The subnet CIDR is invalid."""
45 pass
48 class SiteNotFound(SubnetException):
49 """The site to be used for the subnet does not exist."""
50 pass
53 def create_subnet(samdb, configDn, subnet_name, site_name):
54 """Create a subnet and associate it with a site.
56 :param samdb: A samdb connection
57 :param configDn: The DN of the configuration partition
58 :param subnet_name: name of the subnet to create (a CIDR range)
59 :return: None
60 :raise SubnetAlreadyExists: if the subnet to be created already exists.
61 :raise SiteNotFound: if the site does not exist.
62 """
63 ret = samdb.search(base=configDn, scope=ldb.SCOPE_SUBTREE,
64 expression='(&(objectclass=Site)(cn=%s))' %
65 ldb.binary_encode(site_name))
66 if len(ret) != 1:
67 raise SiteNotFound('A site with the name %s does not exist' %
68 site_name)
69 dn_site = ret[0].dn
71 if not isinstance(subnet_name, str):
72 raise SubnetInvalid("%s is not a valid subnet (not a string)" % subnet_name)
74 dnsubnet = ldb.Dn(samdb, "CN=Subnets,CN=Sites")
75 if dnsubnet.add_base(configDn) == False:
76 raise SubnetException("dnsubnet.add_base() failed")
77 if dnsubnet.add_child("CN=X") == False:
78 raise SubnetException("dnsubnet.add_child() failed")
79 dnsubnet.set_component(0, "CN", subnet_name)
81 try:
82 m = ldb.Message()
83 m.dn = dnsubnet
84 m["objectclass"] = ldb.MessageElement("subnet", FLAG_MOD_ADD,
85 "objectclass")
86 m["siteObject"] = ldb.MessageElement(str(dn_site), FLAG_MOD_ADD,
87 "siteObject")
88 samdb.add(m)
89 except ldb.LdbError as e:
90 (enum, estr) = e.args
91 if enum == ldb.ERR_INVALID_DN_SYNTAX:
92 raise SubnetInvalid("%s is not a valid subnet: %s" % (subnet_name, estr))
93 elif enum == ldb.ERR_ENTRY_ALREADY_EXISTS:
94 # Subnet collisions are checked by exact match only, not
95 # overlapping range. This won't stop you creating
96 # 10.1.1.0/24 when there is already 10.1.0.0/16, or
97 # prevent you from having numerous IPv6 subnets that refer
98 # to the same range (e.g 5::0/16, 5::/16, 5:0:0::/16).
99 raise SubnetAlreadyExists('A subnet with the CIDR %s already exists'
100 % subnet_name)
101 else:
102 raise
105 def delete_subnet(samdb, configDn, subnet_name):
106 """Delete a subnet.
108 :param samdb: A samdb connection
109 :param configDn: The DN of the configuration partition
110 :param subnet_name: Name of the subnet to delete
111 :return: None
112 :raise SubnetNotFound: if the subnet to be deleted does not exist.
114 dnsubnet = ldb.Dn(samdb, "CN=Subnets,CN=Sites")
115 if dnsubnet.add_base(configDn) == False:
116 raise SubnetException("dnsubnet.add_base() failed")
117 if dnsubnet.add_child("CN=X") == False:
118 raise SubnetException("dnsubnet.add_child() failed")
119 dnsubnet.set_component(0, "CN", subnet_name)
121 try:
122 ret = samdb.search(base=dnsubnet, scope=ldb.SCOPE_BASE,
123 expression="objectClass=subnet")
124 if len(ret) != 1:
125 raise SubnetNotFound('Subnet %s does not exist' % subnet_name)
126 except LdbError as e1:
127 (enum, estr) = e1.args
128 if enum == ldb.ERR_NO_SUCH_OBJECT:
129 raise SubnetNotFound('Subnet %s does not exist' % subnet_name)
131 samdb.delete(dnsubnet)
134 def rename_subnet(samdb, configDn, subnet_name, new_name):
135 """Rename a subnet.
137 :param samdb: A samdb connection
138 :param configDn: The DN of the configuration partition
139 :param subnet_name: Name of the subnet to rename
140 :param new_name: New name for the subnet
141 :return: None
142 :raise SubnetNotFound: if the subnet to be renamed does not exist.
143 :raise SubnetExists: if the subnet to be created already exists.
145 dnsubnet = ldb.Dn(samdb, "CN=Subnets,CN=Sites")
146 if dnsubnet.add_base(configDn) == False:
147 raise SubnetException("dnsubnet.add_base() failed")
148 if dnsubnet.add_child("CN=X") == False:
149 raise SubnetException("dnsubnet.add_child() failed")
150 dnsubnet.set_component(0, "CN", subnet_name)
152 newdnsubnet = ldb.Dn(samdb, str(dnsubnet))
153 newdnsubnet.set_component(0, "CN", new_name)
154 try:
155 samdb.rename(dnsubnet, newdnsubnet)
156 except LdbError as e2:
157 (enum, estr) = e2.args
158 if enum == ldb.ERR_NO_SUCH_OBJECT:
159 raise SubnetNotFound('Subnet %s does not exist' % dnsubnet)
160 elif enum == ldb.ERR_ENTRY_ALREADY_EXISTS:
161 raise SubnetAlreadyExists('A subnet with the CIDR %s already exists'
162 % new_name)
163 elif enum == ldb.ERR_INVALID_DN_SYNTAX:
164 raise SubnetInvalid("%s is not a valid subnet: %s" % (new_name,
165 estr))
166 else:
167 raise
170 def set_subnet_site(samdb, configDn, subnet_name, site_name):
171 """Assign a subnet to a site.
173 This dissociates the subnet from its previous site.
175 :param samdb: A samdb connection
176 :param configDn: The DN of the configuration partition
177 :param subnet_name: Name of the subnet
178 :param site_name: Name of the site
179 :return: None
180 :raise SubnetNotFound: if the subnet does not exist.
181 :raise SiteNotFound: if the site does not exist.
184 dnsubnet = ldb.Dn(samdb, "CN=Subnets,CN=Sites")
185 if dnsubnet.add_base(configDn) == False:
186 raise SubnetException("dnsubnet.add_base() failed")
187 if dnsubnet.add_child("CN=X") == False:
188 raise SubnetException("dnsubnet.add_child() failed")
189 dnsubnet.set_component(0, "CN", subnet_name)
191 try:
192 ret = samdb.search(base=dnsubnet, scope=ldb.SCOPE_BASE,
193 expression="objectClass=subnet")
194 if len(ret) != 1:
195 raise SubnetNotFound('Subnet %s does not exist' % subnet_name)
196 except LdbError as e3:
197 (enum, estr) = e3.args
198 if enum == ldb.ERR_NO_SUCH_OBJECT:
199 raise SubnetNotFound('Subnet %s does not exist' % subnet_name)
201 dnsite = ldb.Dn(samdb, "CN=Sites")
202 if dnsite.add_base(configDn) == False:
203 raise SubnetException("dnsites.add_base() failed")
204 if dnsite.add_child("CN=X") == False:
205 raise SubnetException("dnsites.add_child() failed")
206 dnsite.set_component(0, "CN", site_name)
208 dnservers = ldb.Dn(samdb, "CN=Servers")
209 dnservers.add_base(dnsite)
211 try:
212 ret = samdb.search(base=dnsite, scope=ldb.SCOPE_BASE,
213 expression="objectClass=site")
214 if len(ret) != 1:
215 raise SiteNotFoundException('Site %s does not exist' % site_name)
216 except LdbError as e4:
217 (enum, estr) = e4.args
218 if enum == ldb.ERR_NO_SUCH_OBJECT:
219 raise SiteNotFoundException('Site %s does not exist' % site_name)
221 siteDn = str(ret[0].dn)
223 m = ldb.Message()
224 m.dn = dnsubnet
225 m["siteObject"] = ldb.MessageElement(siteDn, FLAG_MOD_REPLACE,
226 "siteObject")
227 samdb.modify(m)