Skip to content

Commit a2e9d26

Browse files
OSPF: Adding dynamically routing capability to VPC by configuring quagga
on VR . Added zone level quagga/ospf config API and UI as addtional tab on zone . Added service offering with ospf . Added service offering for the tier guest network for VPC . Modified system vm template so that quagga is pre-installed . Added various configuration files that are required by Quagga . Added marvin tests for new APIs and unit test . Send quagga config from the server if VPC and tier are dynamically routed . Configure quagga when a VM of the tier is created/destroyed . Added necessary scritps on the vpc router to enable and configure quagga and iptable rules . Multiple Cidr management and netmask based cidr allocation . Added unit tests for cidr management . New dialog for create dynamic VPC and netmask as a field . Marvin tests to test dynmaic vpc service offering . Marvin tests to test dynamic network offering . Converting String based CIDR representation to InetAddress and mask based CIDR object representation that is implemented for ipv4 and with ipv6 placeholder.
1 parent 2b4b8aa commit a2e9d26

File tree

96 files changed

+5513
-821
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+5513
-821
lines changed

api/src/com/cloud/dc/DataCenter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,6 @@ public enum NetworkType {
8181
String getZoneToken();
8282

8383
boolean isLocalStorageEnabled();
84+
85+
boolean isDynamicRoutingEnabled();
8486
}

api/src/com/cloud/network/Network.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public static class Service {
5959
public static final Service SecurityGroup = new Service("SecurityGroup");
6060
public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols);
6161
public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter, Capability.RegionLevelVpc, Capability.StretchedL2Subnet);
62+
public static final Service VPCDynamicRouting = new Service("VPCDynamicRouting");
6263

6364
private final String name;
6465
private final Capability[] caps;
@@ -213,6 +214,7 @@ public static class Capability {
213214
public static final Capability DistributedRouter = new Capability("DistributedRouter");
214215
public static final Capability StretchedL2Subnet = new Capability("StretchedL2Subnet");
215216
public static final Capability RegionLevelVpc = new Capability("RegionLevelVpc");
217+
public static final Capability VPCDynamicRouting = new Capability("VPCDynamicRouting");
216218

217219
private final String name;
218220

@@ -241,9 +243,9 @@ enum Event {
241243

242244
public enum State {
243245

244-
Allocated("Indicates the network configuration is in allocated but not setup"), Setup("Indicates the network configuration is setup"), Implementing(
245-
"Indicates the network configuration is being implemented"), Implemented("Indicates the network configuration is in use"), Shutdown(
246-
"Indicates the network configuration is being destroyed"), Destroy("Indicates that the network is destroyed");
246+
Allocated("Indicates the network configuration is in allocated but not setup"), Setup("Indicates the network configuration is setup"),
247+
Implementing("Indicates the network configuration is being implemented"), Implemented("Indicates the network configuration is in use"),
248+
Shutdown("Indicates the network configuration is being destroyed"), Destroy("Indicates that the network is destroyed");
247249

248250
protected static final StateMachine2<State, Network.Event, Network> s_fsm = new StateMachine2<State, Network.Event, Network>();
249251

api/src/com/cloud/network/PhysicalNetworkServiceProvider.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,6 @@ public enum State {
6767
String getUuid();
6868

6969
boolean isNetworkAclServiceProvided();
70+
71+
boolean isDynamicRoutingProvided();
7072
}
Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package com.cloud.network.vpc;
19+
20+
import java.util.Arrays;
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
24+
import org.apache.cloudstack.utils.net.cidr.CIDR;
25+
import org.apache.cloudstack.utils.net.cidr.CIDRException;
26+
import org.apache.cloudstack.utils.net.cidr.CIDRFactory;
27+
import org.apache.commons.lang.ArrayUtils;
28+
import org.apache.commons.lang.StringUtils;
29+
30+
import com.cloud.exception.InvalidParameterValueException;
31+
32+
public class OSPFZoneConfig {
33+
34+
private long zoneId;
35+
private Protocol protocol;
36+
private String ospfArea;
37+
private Short helloInterval;
38+
private Short deadInterval;
39+
private Short retransmitInterval;
40+
private Short transitDelay;
41+
private Authentication authentication;
42+
private String password;
43+
private CIDR[] superCIDRList;
44+
private Boolean enabled;
45+
46+
public static final String s_protocol = "protocol";
47+
public static final String s_area = "area";
48+
public static final String s_helloInterval = "hellointerval";
49+
public static final String s_deadInterval = "deadinterval";
50+
public static final String s_retransmitInterval = "retransmitinterval";
51+
public static final String s_transitDelay = "transitdelay";
52+
public static final String s_authentication = "authentication";
53+
public static final String s_superCIDR = "supercidr";
54+
public static final String s_password = "password";
55+
public static final String s_enabled = "enabled";
56+
57+
public Protocol getProtocol() {
58+
return protocol;
59+
}
60+
61+
public void setProtocol(String str) {
62+
this.protocol = str == null ? Protocol.OSPF : Protocol.valueOf(str);
63+
}
64+
65+
public String getOspfArea() {
66+
return ospfArea;
67+
}
68+
69+
public void setOspfArea(String ospfArea) {
70+
this.ospfArea = ospfArea == null ? "0" : ospfArea;
71+
}
72+
73+
public Short getHelloInterval() {
74+
return helloInterval;
75+
}
76+
77+
public void setHelloInterval(String string) {
78+
this.helloInterval = string == null ? 10 : Short.valueOf(string);
79+
if (this.helloInterval > 65535 || this.helloInterval < 1){
80+
throw new IllegalArgumentException("The value of hello interval should be from 1 to 65535 and now " + this.helloInterval);
81+
}
82+
}
83+
84+
public Short getDeadInterval() {
85+
return deadInterval;
86+
}
87+
88+
public void setDeadInterval(String deadInterval) {
89+
this.deadInterval = deadInterval == null ? 40 : Short.valueOf(deadInterval);
90+
if (this.deadInterval > 65535 || this.helloInterval < 1){
91+
throw new IllegalArgumentException("The value of dead interval should be from 1 to 65535 and now " + this.deadInterval);
92+
}
93+
}
94+
95+
public Short getRetransmitInterval() {
96+
return retransmitInterval;
97+
}
98+
99+
public void setRetransmitInterval(String retransmitInterval) {
100+
this.retransmitInterval = retransmitInterval == null ? 5 : Short.valueOf(retransmitInterval);
101+
if (this.retransmitInterval > 65535 || this.retransmitInterval < 1){
102+
throw new IllegalArgumentException("The value of retransmit interval should be from 1 to 65535 and now " + this.retransmitInterval);
103+
}
104+
}
105+
106+
public Short getTransitDelay() {
107+
return transitDelay;
108+
}
109+
110+
public void setTransitDelay(String transitDelay) {
111+
this.transitDelay = transitDelay == null ? 1 : Short.valueOf(transitDelay);
112+
if (this.transitDelay > 65535 || this.transitDelay < 1){
113+
throw new IllegalArgumentException("The value of transit rDelay should be from 1 to 65535 and now " + this.retransmitInterval);
114+
}
115+
}
116+
117+
public Authentication getAuthentication() {
118+
return authentication;
119+
}
120+
121+
public void setAuthentication(String authentication) {
122+
this.authentication = authentication == null ? Authentication.MD5 : Authentication.valueOf(authentication);
123+
}
124+
125+
public String getPassword() {
126+
return password = password == null ? "" : password;
127+
}
128+
129+
public void setPassword(String password) {
130+
this.password = password;
131+
}
132+
133+
public CIDR[] getSuperCIDR() {
134+
return superCIDRList;
135+
}
136+
137+
public void setSuperCIDR(String superCIDR) {
138+
try {
139+
this.superCIDRList = superCIDR == null ? new CIDR[0] : CIDRFactory.convertToCIDR(superCIDR.split(","));
140+
} catch (CIDRException e) {
141+
// TODO Auto-generated catch block
142+
throw new InvalidParameterValueException("The CIDR value for Super CIDR is invalid " + superCIDR);
143+
}
144+
}
145+
146+
public Boolean getEnabled() {
147+
return enabled;
148+
}
149+
150+
public void setEnabled(String enabled) {
151+
this.enabled = enabled == null ? Boolean.FALSE : Boolean.valueOf(enabled);
152+
}
153+
154+
public enum Params {
155+
PROTOCOL, AREA, HELLO_INTERVAL, DEAD_INTERVAL, RETRANSMIT_INTERVAL, TRANSIT_DELAY, AUTHENTICATION, SUPER_CIDR, PASSWORD, ENABLED
156+
}
157+
158+
public enum Protocol {
159+
OSPF
160+
}
161+
162+
public enum Authentication {
163+
MD5, PLAIN_TEXT
164+
}
165+
166+
public OSPFZoneConfig(final Map<String, String> details) {
167+
this.setProtocol(details.get(Params.PROTOCOL.name()) );
168+
this.setOspfArea(details.get(Params.AREA.name()));
169+
this.setHelloInterval(details.get(Params.HELLO_INTERVAL.name()));
170+
this.setDeadInterval(details.get(Params.DEAD_INTERVAL.name()));
171+
this.setRetransmitInterval(details.get(Params.RETRANSMIT_INTERVAL.name()));
172+
this.setTransitDelay(details.get(Params.TRANSIT_DELAY.name()));
173+
this.setAuthentication( details.get(Params.AUTHENTICATION.name()));
174+
this.setPassword(details.get(Params.PASSWORD.name()));
175+
this.setSuperCIDR(details.get(Params.SUPER_CIDR.name()));
176+
this.setEnabled(details.get(Params.ENABLED.name()));
177+
}
178+
179+
public void setValues(final String protocol, final String ospfArea, final Short helloInterval, final Short deadInterval, final Short retransmitInterval,
180+
final Short transitDelay, final String authentication, final String quaggaPassword, final String superCIDRList, final Boolean enabled) throws CIDRException {
181+
if (protocol != null) {
182+
if ((Protocol.OSPF.name().equals(protocol))) {
183+
this.protocol = Protocol.valueOf(protocol);
184+
} else {
185+
throw new InvalidParameterValueException("The quagga protocal can have values of OSPF only " + protocol);
186+
}
187+
}
188+
if (ospfArea != null) {
189+
this.ospfArea = ospfArea;
190+
}
191+
if (helloInterval != null) {
192+
this.helloInterval = helloInterval;
193+
}
194+
if (deadInterval != null) {
195+
this.deadInterval = deadInterval;
196+
}
197+
if (retransmitInterval != null) {
198+
this.retransmitInterval = retransmitInterval;
199+
}
200+
if (transitDelay != null) {
201+
this.transitDelay = transitDelay;
202+
}
203+
if (authentication != null) {
204+
if (Authentication.MD5.name().equals(authentication) || Authentication.PLAIN_TEXT.name().equals(authentication)) {
205+
this.authentication = Authentication.valueOf(authentication);
206+
} else {
207+
throw new InvalidParameterValueException("The quagga authentication can have values of MD5 or PLAIN_TEXT and not " + protocol);
208+
}
209+
}
210+
if (quaggaPassword != null) {
211+
this.password = quaggaPassword;
212+
}
213+
if (superCIDRList != null) {
214+
this.superCIDRList = CIDRFactory.getCIDRList(superCIDRList);
215+
}
216+
if (enabled != null) {
217+
this.enabled = enabled;
218+
}
219+
}
220+
221+
public void setValues(Map<String, String> details) throws CIDRException {
222+
Protocol protocol = Protocol.valueOf(details.get(Params.PROTOCOL.name()));
223+
String ospfArea = details.get(Params.AREA.name());
224+
Short helloInterval = Short.valueOf(details.get(Params.HELLO_INTERVAL.name()));
225+
Short deadInterval = Short.valueOf(details.get(Params.DEAD_INTERVAL.name()));
226+
Short retransmitInterval = Short.valueOf(details.get(Params.RETRANSMIT_INTERVAL.name()));
227+
Short transitDelay = Short.valueOf(details.get(Params.TRANSIT_DELAY.name()));
228+
Authentication authentication = Authentication.valueOf(details.get(Params.AUTHENTICATION.name()));
229+
String quaggaPassword = details.get(Params.PASSWORD.name());
230+
String superCIDRList = details.get(Params.SUPER_CIDR.name());
231+
Boolean enabled = Boolean.valueOf(details.get(Params.ENABLED.name()));
232+
233+
if (protocol != null) {
234+
if (Protocol.OSPF == protocol) {
235+
this.protocol = protocol;
236+
} else {
237+
throw new InvalidParameterValueException("The quagga protocal can have values of OSPF " + protocol);
238+
}
239+
}
240+
if (ospfArea != null) {
241+
this.ospfArea = ospfArea;
242+
}
243+
if (helloInterval != null) {
244+
this.helloInterval = helloInterval;
245+
}
246+
if (deadInterval != null) {
247+
this.deadInterval = deadInterval;
248+
}
249+
if (retransmitInterval != null) {
250+
this.retransmitInterval = retransmitInterval;
251+
}
252+
if (transitDelay != null) {
253+
this.transitDelay = transitDelay;
254+
}
255+
if (authentication != null) {
256+
if (Authentication.MD5 == authentication || Authentication.PLAIN_TEXT == authentication) {
257+
this.authentication = authentication;
258+
} else {
259+
throw new InvalidParameterValueException("The quagga authentication can have values of MD5 or PLAIN_TEXT and not " + authentication);
260+
}
261+
}
262+
if (quaggaPassword != null) {
263+
this.password = quaggaPassword;
264+
}
265+
if (superCIDRList != null) {
266+
this.superCIDRList = CIDRFactory.getCIDRList(superCIDRList);
267+
}
268+
if (enabled != null) {
269+
this.enabled = enabled;
270+
}
271+
}
272+
273+
public Map<String, String> getValues() throws CIDRException {
274+
Map<String, String> details = new HashMap<String, String>();
275+
if (protocol != null) {
276+
if ((Protocol.OSPF.name().equals(protocol))) {
277+
details.put(Params.PROTOCOL.name(), protocol.name());
278+
} else {
279+
details.put(Params.PROTOCOL.name(), Protocol.OSPF.name());
280+
}
281+
}
282+
if (ospfArea != null) {
283+
details.put(Params.AREA.name(), ospfArea);
284+
}
285+
if (helloInterval != null) {
286+
details.put(Params.HELLO_INTERVAL.name(), helloInterval.toString());
287+
}
288+
if (deadInterval != null) {
289+
details.put(Params.DEAD_INTERVAL.name(), deadInterval.toString());
290+
}
291+
if (retransmitInterval != null) {
292+
details.put(Params.RETRANSMIT_INTERVAL.name(), retransmitInterval.toString());
293+
}
294+
if (transitDelay != null) {
295+
details.put(Params.TRANSIT_DELAY.name(), transitDelay.toString());
296+
}
297+
if (authentication != null) {
298+
if (Authentication.MD5.name().equals(authentication) || Authentication.PLAIN_TEXT.name().equals(authentication)) {
299+
details.put(Params.AUTHENTICATION.name(), authentication.name());
300+
} else {
301+
details.put(Params.AUTHENTICATION.name(), Authentication.MD5.name());
302+
}
303+
}
304+
if (password != null) {
305+
details.put(Params.PASSWORD.name(), password);
306+
}
307+
if (!ArrayUtils.isEmpty(superCIDRList)) {
308+
if (!CIDRFactory.cidrListConsistency(superCIDRList)) {
309+
throw new InvalidParameterValueException("The cidr list is not consistent " + Arrays.toString(superCIDRList));
310+
}
311+
details.put(Params.SUPER_CIDR.name(), StringUtils.join(superCIDRList, ','));
312+
313+
} else {
314+
details.put(Params.SUPER_CIDR.name(), "");
315+
}
316+
if (enabled != null) {
317+
details.put(Params.ENABLED.name(), enabled.toString());
318+
}
319+
320+
return details;
321+
}
322+
323+
@Override
324+
public String toString() {
325+
return "OSPFZoneConfig [zoneId=" + zoneId + ", protocol=" + protocol + ", ospfArea=" + ospfArea + ", helloInterval=" + helloInterval + ", deadInterval=" + deadInterval
326+
+ ", retransmitInterval=" + retransmitInterval + ", transitDelay=" + transitDelay + ", authentication=" + authentication + ", password=" + password
327+
+ ", superCIDRList=" + Arrays.toString(superCIDRList) + ", enabled=" + enabled + "]";
328+
}
329+
}

api/src/com/cloud/network/vpc/Vpc.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,5 @@ public enum State {
8787
* @return true if VPC spans multiple zones in the region
8888
*/
8989
boolean isRegionLevelVpc();
90+
9091
}

api/src/com/cloud/network/vpc/VpcOffering.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
import org.apache.cloudstack.api.InternalIdentity;
2121

2222
public interface VpcOffering extends InternalIdentity, Identity {
23+
2324
public enum State {
2425
Disabled, Enabled
2526
}
2627

2728
public static final String defaultVPCOfferingName = "Default VPC offering";
2829
public static final String defaultVPCNSOfferingName = "Default VPC offering with Netscaler";
2930
public static final String redundantVPCOfferingName = "Redundant VPC offering";
31+
public static final String routedVPCOfferingName = "Default Dynamically Routed VPC offering";
3032

3133
/**
3234
*

0 commit comments

Comments
 (0)