diff --git a/api/src/com/cloud/agent/api/routing/SetStaticRouteCommand.java b/api/src/com/cloud/agent/api/routing/SetStaticRouteCommand.java index 1ab59d7174e..4f335af7fdd 100644 --- a/api/src/com/cloud/agent/api/routing/SetStaticRouteCommand.java +++ b/api/src/com/cloud/agent/api/routing/SetStaticRouteCommand.java @@ -12,8 +12,12 @@ // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.agent.api.routing; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import com.cloud.agent.api.to.NetworkACLTO; +import com.cloud.network.vpc.StaticRoute; import com.cloud.network.vpc.StaticRouteProfile; /** @@ -32,4 +36,19 @@ public class SetStaticRouteCommand extends NetworkElementCommand{ public StaticRouteProfile[] getStaticRoutes() { return staticRoutes; } + + public String[][] generateSRouteRules() { + String [][] result = new String [2][]; + Set toAdd = new HashSet(); + for (StaticRouteProfile route: staticRoutes) { + /* example : ip:gateway:cidr, + */ + if( route.getState() == StaticRoute.State.Active || route.getState() == StaticRoute.State.Add ) { + String entry = route.getIp4Address()+ ":" + route.getGateway() + ":" + route.getCidr(); + toAdd.add(entry); + } + } + result[0] = toAdd.toArray(new String[toAdd.size()]); + return result; + } } diff --git a/api/src/com/cloud/api/commands/UpdateNetworkCmd.java b/api/src/com/cloud/api/commands/UpdateNetworkCmd.java index bde3054e901..22d111d33ac 100644 --- a/api/src/com/cloud/api/commands/UpdateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/UpdateNetworkCmd.java @@ -113,7 +113,8 @@ public class UpdateNetworkCmd extends BaseAsyncCmd { public void execute() throws InsufficientCapacityException, ConcurrentOperationException{ User callerUser = _accountService.getActiveUser(UserContext.current().getCallerUserId()); Account callerAccount = _accountService.getActiveAccountById(callerUser.getAccountId()); - Network result = _networkService.updateGuestNetwork(getId(), getNetworkName(), getDisplayText(), callerAccount, callerUser, getNetworkDomain(), getNetworkOfferingId(), getChangeCidr()); + Network result = _networkService.updateGuestNetwork(getId(), getNetworkName(), getDisplayText(), callerAccount, + callerUser, getNetworkDomain(), getNetworkOfferingId(), getChangeCidr()); if (result != null) { NetworkResponse response = _responseGenerator.createNetworkResponse(result); response.setResponseName(getCommandName()); diff --git a/api/src/com/cloud/api/response/Site2SiteVpnConnectionResponse.java b/api/src/com/cloud/api/response/Site2SiteVpnConnectionResponse.java index 41508202cfd..9845b06d04d 100644 --- a/api/src/com/cloud/api/response/Site2SiteVpnConnectionResponse.java +++ b/api/src/com/cloud/api/response/Site2SiteVpnConnectionResponse.java @@ -26,10 +26,31 @@ public class Site2SiteVpnConnectionResponse extends BaseResponse { @SerializedName(ApiConstants.S2S_VPN_GATEWAY_ID) @Param(description="the vpn gateway ID") private IdentityProxy vpnGatewayId= new IdentityProxy("s2s_vpn_gateway"); + + @SerializedName(ApiConstants.PUBLIC_IP) @Param(description="the public IP address") //from VpnGateway + private String ip; @SerializedName(ApiConstants.S2S_CUSTOMER_GATEWAY_ID) @Param(description="the customer gateway ID") private IdentityProxy customerGatewayId = new IdentityProxy("s2s_customer_gateway"); + + @SerializedName(ApiConstants.GATEWAY) @Param(description="public ip address id of the customer gateway") //from CustomerGateway + private String gatewayIp; + @SerializedName(ApiConstants.CIDR_LIST) @Param(description="guest cidr list of the customer gateway") //from CustomerGateway + private String guestCidrList; + + @SerializedName(ApiConstants.IPSEC_PSK) @Param(description="IPsec Preshared-Key of the customer gateway") //from CustomerGateway + private String ipsecPsk; + + @SerializedName(ApiConstants.IKE_POLICY) @Param(description="IKE policy of the customer gateway") //from CustomerGateway + private String ikePolicy; + + @SerializedName(ApiConstants.ESP_POLICY) @Param(description="ESP policy of the customer gateway") //from CustomerGateway + private String espPolicy; + + @SerializedName(ApiConstants.LIFETIME) @Param(description="Lifetime of vpn connection to the customer gateway, in seconds") //from CustomerGateway + private Long lifetime; + @SerializedName(ApiConstants.CREATED) @Param(description="the date and time the host was created") private Date created; @@ -44,10 +65,38 @@ public class Site2SiteVpnConnectionResponse extends BaseResponse { this.vpnGatewayId.setValue(vpnGatewayId); } + public void setIp(String ip) { + this.ip = ip; + } + public void setCustomerGatewayId(Long customerGatewayId) { this.customerGatewayId.setValue(customerGatewayId); } - + + public void setGatewayIp(String gatewayIp) { + this.gatewayIp = gatewayIp; + } + + public void setGuestCidrList(String guestCidrList) { + this.guestCidrList = guestCidrList; + } + + public void setIpsecPsk(String ipsecPsk) { + this.ipsecPsk = ipsecPsk; + } + + public void setIkePolicy(String ikePolicy) { + this.ikePolicy = ikePolicy; + } + + public void setEspPolicy(String espPolicy) { + this.espPolicy = espPolicy; + } + + public void setLifetime(Long lifetime) { + this.lifetime = lifetime; + } + public void setCreated(Date created) { this.created = created; } diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 17ea4e72c61..b8ebb93fe8a 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -42,7 +42,7 @@ public interface Network extends ControlledEntity { public static final Service Dns = new Service("Dns", Capability.AllowDnsSuffixModification); public static final Service Gateway = new Service("Gateway"); public static final Service Firewall = new Service("Firewall", Capability.SupportedProtocols, - Capability.MultipleIps, Capability.TrafficStatistics, Capability.FirewallType); + Capability.MultipleIps, Capability.TrafficStatistics); public static final Service Lb = new Service("Lb", Capability.SupportedLBAlgorithms, Capability.SupportedLBIsolation, Capability.SupportedProtocols, Capability.TrafficStatistics, Capability.LoadBalancingSupportedIps, Capability.SupportedStickinessMethods, Capability.ElasticLb); @@ -51,6 +51,7 @@ public interface Network extends ControlledEntity { public static final Service StaticNat = new Service("StaticNat", Capability.ElasticIp); public static final Service PortForwarding = new Service("PortForwarding"); public static final Service SecurityGroup = new Service("SecurityGroup"); + public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols); private String name; private Capability[] caps; @@ -160,7 +161,6 @@ public interface Network extends ControlledEntity { public static final Capability RedundantRouter = new Capability("RedundantRouter"); public static final Capability ElasticIp = new Capability("ElasticIp"); public static final Capability ElasticLb = new Capability("ElasticLb"); - public static final Capability FirewallType = new Capability("FirewallType"); private String name; diff --git a/api/src/com/cloud/network/vpc/PrivateIp.java b/api/src/com/cloud/network/vpc/PrivateIp.java index 771a2aa6386..cfcd41b0ccc 100644 --- a/api/src/com/cloud/network/vpc/PrivateIp.java +++ b/api/src/com/cloud/network/vpc/PrivateIp.java @@ -41,5 +41,7 @@ public interface PrivateIp { * @return */ String getMacAddress(); + + long getNetworkId(); } diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 4a700cd9177..17e8a5cef00 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -7413,9 +7413,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String [][] rules = cmd.generateFwRules(); StringBuilder sb = new StringBuilder(); String[] aclRules = rules[0]; - if (aclRules.length == 0) { - return new SetNetworkACLAnswer(cmd, true, results); - } for (int i = 0; i < aclRules.length; i++) { sb.append(aclRules[i]).append(','); @@ -7475,7 +7472,32 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private SetStaticRouteAnswer execute(SetStaticRouteCommand cmd) { - // TODO Auto-generated method stub - return new SetStaticRouteAnswer(cmd, true, null); + String[] results = new String[cmd.getStaticRoutes().length]; + String callResult; + Connection conn = getConnection(); + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + try { + String [][] rules = cmd.generateSRouteRules(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < rules.length; i++) { + sb.append(rules[i]).append(','); + } + + String args = "vpc_staticroute.sh " + routerIp; + args += " -a " + sb.toString(); + callResult = callHostPlugin(conn, "vmops", "routerProxy", "args", args); + if (callResult == null || callResult.isEmpty()) { + //FIXME - in the future we have to process each rule separately; now we temporarily set every rule to be false if single rule fails + for (int i=0; i < results.length; i++) { + results[i] = "Failed"; + } + return new SetStaticRouteAnswer(cmd, false, results); + } + return new SetStaticRouteAnswer(cmd, true, results); + } catch (Exception e) { + String msg = "SetNetworkACL failed due to " + e.toString(); + s_logger.error(msg, e); + return new SetStaticRouteAnswer(cmd, false, results); + } } } diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config index d46a1e733e8..3a8f11d8de3 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -600,7 +600,12 @@ EOF fi ip route delete default + # create route table for static route + sudo echo "252 static_route" >> /etc/iproute2/rt_tables 2>/dev/null + sudo echo "251 static_route_back" >> /etc/iproute2/rt_tables 2>/dev/null + sudo ip rule add from $VPCCIDR table static_route 2>/dev/null + sudo ip rule add from $VPCCIDR table static_route_back 2>/dev/null sed -i /gateway/d /etc/hosts @@ -772,6 +777,7 @@ setup_default() { auto lo iface lo inet loopback EOF + cp -f /etc/iptables/rt_tables_init /etc/iproute2/rt_tables } change_password() { @@ -951,6 +957,9 @@ for i in $CMDLINE vmpassword) VM_PASSWORD=$VALUE ;; + vpccidr) + VPCCIDR=$VALUE + ;; esac done } diff --git a/patches/systemvm/debian/config/etc/iptables/rt_tables_init b/patches/systemvm/debian/config/etc/iptables/rt_tables_init new file mode 100644 index 00000000000..07ffaf3baa5 --- /dev/null +++ b/patches/systemvm/debian/config/etc/iptables/rt_tables_init @@ -0,0 +1,11 @@ +# +# reserved values +# +255 local +254 main +253 default +0 unspec +# +# local +# +#1 inr.ruhep diff --git a/patches/systemvm/debian/config/opt/cloud/bin/cloud-nic.sh b/patches/systemvm/debian/config/opt/cloud/bin/cloud-nic.sh index 3d8de19ba5f..11b70973abb 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/cloud-nic.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/cloud-nic.sh @@ -16,9 +16,9 @@ unplug_nic() { sudo ip route flush table $tableName sudo sed -i /"$tableNo $tableName"/d /etc/iproute2/rt_tables 2>/dev/null sudo ip route flush cache - # remove usage + # remove rules sudo iptables -t mangle -F NETWORK_STATS_$dev 2>/dev/null - iptables-save | grep NETWORK_STATS_$dev | grep "\-A" | while read rule + iptables-save -t mangle | grep NETWORK_STATS_$dev | grep "\-A" | while read rule do rule=$(echo $rule | sed 's/\-A/\-D/') sudo iptables -t mangle $rule diff --git a/patches/systemvm/debian/config/opt/cloud/bin/ipsectunnel.sh b/patches/systemvm/debian/config/opt/cloud/bin/ipsectunnel.sh index 7426d4b6166..6ff8793f2c0 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/ipsectunnel.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/ipsectunnel.sh @@ -118,7 +118,7 @@ ipsec_tunnel_add() { for i in {1..4} do logger -t cloud "$(basename $0): checking connection status..." - ./checks2svpn.sh $rightpeer + /opt/cloud/bin/checks2svpn.sh $rightpeer result=$? if [ $result -eq 0 ] then diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_acl.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_acl.sh index 7ef648d5232..4b83397fcde 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_acl.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_acl.sh @@ -30,46 +30,46 @@ usage() { #set -x #FIXME: eating up the error code during execution of iptables acl_remove_backup() { - sudo iptables -F _ACL_INBOUND_$ip 2>/dev/null - sudo iptables -D FORWARD -o $dev -d $gcidr -j _ACL_INBOUND_$ip 2>/dev/null - sudo iptables -X _ACL_INBOUND_$ip 2>/dev/null - sudo iptables -F _ACL_OUTBOUND_$ip 2>/dev/null - sudo iptables -D FORWARD -i $dev -s $gcidr -j _ACL_OUTBOUND_$ip 2>/dev/null - sudo iptables -X _ACL_OUTBOUND_$ip 2>/dev/null + sudo iptables -F _ACL_INBOUND_$dev 2>/dev/null + sudo iptables -D FORWARD -o $dev -d $gcidr -j _ACL_INBOUND_$dev 2>/dev/null + sudo iptables -X _ACL_INBOUND_$dev 2>/dev/null + sudo iptables -F _ACL_OUTBOUND_$dev 2>/dev/null + sudo iptables -D FORWARD -i $dev -s $gcidr -j _ACL_OUTBOUND_$dev 2>/dev/null + sudo iptables -X _ACL_OUTBOUND_$dev 2>/dev/null } acl_remove() { - sudo iptables -F ACL_INBOUND_$ip 2>/dev/null - sudo iptables -D FORWARD -o $dev -d $gcidr -j ACL_INBOUND_$ip 2>/dev/null - sudo iptables -X ACL_INBOUND_$ip 2>/dev/null - sudo iptables -F ACL_OUTBOUND_$ip 2>/dev/null - sudo iptables -D FORWARD -i $dev -s $gcidr -j ACL_OUTBOUND_$ip 2>/dev/null - sudo iptables -X ACL_OUTBOUND_$ip 2>/dev/null + sudo iptables -F ACL_INBOUND_$dev 2>/dev/null + sudo iptables -D FORWARD -o $dev -d $gcidr -j ACL_INBOUND_$dev 2>/dev/null + sudo iptables -X ACL_INBOUND_$dev 2>/dev/null + sudo iptables -F ACL_OUTBOUND_$dev 2>/dev/null + sudo iptables -D FORWARD -i $dev -s $gcidr -j ACL_OUTBOUND_$dev 2>/dev/null + sudo iptables -X ACL_OUTBOUND_$dev 2>/dev/null } acl_restore() { acl_remove - sudo iptables -E _ACL_INBOUND_$ip ACL_INBOUND_$ip 2>/dev/null - sudo iptables -E _ACL_OUTBOUND_$ip ACL_OUTBOUND_$ip 2>/dev/null + sudo iptables -E _ACL_INBOUND_$dev ACL_INBOUND_$dev 2>/dev/null + sudo iptables -E _ACL_OUTBOUND_$dev ACL_OUTBOUND_$dev 2>/dev/null } acl_save() { acl_remove_backup - sudo iptables -E ACL_INBOUND_$ip _ACL_INBOUND_$ip 2>/dev/null - sudo iptables -E ACL_OUTBOUND_$ip _ACL_OUTBOUND_$ip 2>/dev/null + sudo iptables -E ACL_INBOUND_$dev _ACL_INBOUND_$dev 2>/dev/null + sudo iptables -E ACL_OUTBOUND_$dev _ACL_OUTBOUND_$dev 2>/dev/null } acl_chain_for_guest_network () { acl_save # inbound - sudo iptables -N ACL_INBOUND_$ip 2>/dev/null + sudo iptables -N ACL_INBOUND_$dev 2>/dev/null # drop if no rules match (this will be the last rule in the chain) - sudo iptables -A ACL_INBOUND_$ip -j DROP 2>/dev/null - sudo iptables -A FORWARD -o $dev -d $gcidr -j ACL_INBOUND_$ip 2>/dev/null + sudo iptables -A ACL_INBOUND_$dev -j DROP 2>/dev/null + sudo iptables -A FORWARD -o $dev -d $gcidr -j ACL_INBOUND_$dev 2>/dev/null # outbound - sudo iptables -N ACL_OUTBOUND_$ip 2>/dev/null - sudo iptables -A ACL_OUTBOUND_$ip -j DROP 2>/dev/null - sudo iptables -A FORWARD -i $dev -s $gcidr -j ACL_OUTBOUND_$ip 2>/dev/null + sudo iptables -N ACL_OUTBOUND_$dev 2>/dev/null + sudo iptables -A ACL_OUTBOUND_$dev -j DROP 2>/dev/null + sudo iptables -A FORWARD -i $dev -s $gcidr -j ACL_OUTBOUND_$dev 2>/dev/null } @@ -102,19 +102,19 @@ acl_entry_for_guest_network() { [ "$sport" == "-1" ] && typecode="any" if [ "$ttype" == "Ingress" ] then - sudo iptables -I ACL_INBOUND_$ip -p $prot -s $lcidr \ + sudo iptables -I ACL_INBOUND_$dev -p $prot -s $lcidr \ --icmp-type $typecode -j ACCEPT else - sudo iptables -I ACL_OUTBOUND_$ip -p $prot -d $lcidr \ + sudo iptables -I ACL_OUTBOUND_$dev -p $prot -d $lcidr \ --icmp-type $typecode -j ACCEPT fi else if [ "$ttype" == "Ingress" ] then - sudo iptables -I ACL_INBOUND_$ip -p $prot -s $lcidr \ + sudo iptables -I ACL_INBOUND_$dev -p $prot -s $lcidr \ $DPORT -j ACCEPT else - sudo iptables -I ACL_OUTBOUND_$ip -p $prot -d $lcidr \ + sudo iptables -I ACL_OUTBOUND_$dev -p $prot -d $lcidr \ $DPORT -j ACCEPT fi fi diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_guestnw.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_guestnw.sh index 56e59813266..54ac7c8b7ae 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_guestnw.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_guestnw.sh @@ -87,9 +87,13 @@ create_guest_network() { sudo iptables -D INPUT -i $dev -p udp -m udp --dport 53 -j ACCEPT sudo iptables -A INPUT -i $dev -p udp -m udp --dport 67 -j ACCEPT sudo iptables -A INPUT -i $dev -p udp -m udp --dport 53 -j ACCEPT + # restore mark from connection mark local tableName="Table_$dev" sudo ip route add $subnet/$mask dev $dev table $tableName proto static sudo iptables -t mangle -A PREROUTING -i $dev -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark + # set up hairpin + sudo iptables -t nat -A POSTROUTING -s $subnet/$mask -o $dev -j SNAT --to-source $ip + setup_usage setup_dnsmasq } @@ -101,6 +105,7 @@ destroy_guest_network() { sudo iptables -D INPUT -i $dev -p udp -m udp --dport 67 -j ACCEPT sudo iptables -D INPUT -i $dev -p udp -m udp --dport 53 -j ACCEPT sudo iptables -t mangle -D PREROUTING -i $dev -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark + sudo iptables -t nat -A POSTROUTING -s $subnet/$mask -o $dev -j SNAT --to-source $ip desetup_dnsmasq } diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_staticroute.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_staticroute.sh index 2a4593c7603..2c3f3ee9810 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_staticroute.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_staticroute.sh @@ -23,56 +23,68 @@ then fi usage() { - printf "Usage: %s: (-A|-D) -c < cidr > -l -g < gateway> \n" $(basename $0) >&2 + printf "Usage: %s: -a < routes > \n" $(basename $0) >&2 } #set -x +flush_table_backup() { + flush_table "static_route_back" +} + +flush_table() { + local tab=$1 + sudo ip route flush table $tab +} + +copy_table() { + local from=$1 + local to=$2 + sudo ip route show table $from | while read route + do + sudo ip route add table $to $route + done +} + +backup_table() { + flush_table "static_route_back" + copy_table "static_route" "static_route_back" + flush table "static_route" +} + +restore_table() { + flush_table "static_route" + copy_table "static_route_back" "static_route" + flush table "static_route_back" +} + static_route() { - local op=$1 - local publicIp=$2 - local gateway=$3 - local cidr=$4 - + local rule=$1 + local ip=$(echo $rule | cut -d: -f1) + local gateway=$(echo $rule | cut -d: -f2) + local cidr=$(echo $rule | cut -d: -f3) logger -t cloud "$(basename $0): static route: public ip=$publicIp \ - gateway=$gateway cidr=$cidr op=$op" - #if adding, this might be a duplicate, so delete the old one first - [ "$op" == "add" ] && static_routet "del" $publicIp $gateway $cidr - - sudo ip route $op $cidr dev $ethDev via $gateway &>> $OUTFILE + gateway=$gateway cidr=$cidr" + local dev=$(getDevByIp $ip) + if [ $? -gt 0 ] + then + return 1 + fi + sudo ip route table static_route add $cidr dev $dev via $gateway &>> $OUTFILE result=$? logger -t cloud "$(basename $0): done static route: public ip=$publicIp \ - gateway=$gateway cidr=$cidr op=$op" - - if [ "$op" == "del" ] - then - return 0 - fi + gateway=$gateway cidr=$cidr" return $result } - - gflag= -lflag= -cflag= -op="" -while getopts 'ADg:l:c:' OPTION +aflag= +while getopts 'a:' OPTION do case $OPTION in - A) op="add" - ;; - D) op="del" - ;; - g) gflag=1 - gateway="$OPTARG" - ;; - l) lflag=1 - publicIp="$OPTARG" - ;; - c) cflag=1 - cidr="$OPTARG" + a) aflag=1 + rules="$OPTARG" ;; ?) usage unlock_exit 2 $lock $locked @@ -80,14 +92,35 @@ do esac done -ethDev=$(getEthByIp $publicIp) -result=$? -if [ $result -gt 0 ] +if [ -n "$rules" ] then - unlock_exit $result $lock $locked + rules_list=$(echo $rules | cut -d, --output-delimiter=" ") fi -OUTFILE=$(mktemp) -static_route $op $publicIp $gateway $cidr -result=$? -unlock_exit $result $lock $locked +success=0 + +backup_table + +for r in $rules_list +do + static_route $r + success=$? + if [ $success -gt 0 ] + then + logger -t cloud "$(basename $0): failure to apply fw rules for guest network: $gcidr" + break + else + logger -t cloud "$(basename $0): successful in applying fw rules for guest network: $gcidr" + fi +done + +if [ $success -gt 0 ] +then + logger -t cloud "$(basename $0): restoring from backup for guest network: $gcidr" + restore_table +else + logger -t cloud "$(basename $0): deleting backup for guest network: $gcidr" + flush_table_backup +fi +unlock_exit $success $lock $locked + diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 64c7fef6792..29d5a06af00 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -58,6 +58,8 @@ import com.cloud.network.NetworkManager; import com.cloud.network.NetworkProfile; import com.cloud.network.NetworkRuleConfigVO; import com.cloud.network.NetworkVO; +import com.cloud.network.Site2SiteVpnGatewayVO; +import com.cloud.network.Site2SiteCustomerGatewayVO; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.FirewallRulesCidrsDao; import com.cloud.network.dao.IPAddressDao; @@ -65,6 +67,8 @@ import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkDomainDao; import com.cloud.network.dao.NetworkRuleConfigDao; +import com.cloud.network.dao.Site2SiteVpnGatewayDao; +import com.cloud.network.dao.Site2SiteCustomerGatewayDao; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupManager; import com.cloud.network.security.SecurityGroupVO; @@ -177,6 +181,8 @@ public class ApiDBUtils { private static UserVmDao _userVmDao; private static VlanDao _vlanDao; private static VolumeDao _volumeDao; + private static Site2SiteVpnGatewayDao _site2SiteVpnGatewayDao; + private static Site2SiteCustomerGatewayDao _site2SiteCustomerGatewayDao; private static VolumeHostDao _volumeHostDao; private static DataCenterDao _zoneDao; private static NetworkOfferingDao _networkOfferingDao; @@ -232,6 +238,8 @@ public class ApiDBUtils { _userVmDao = locator.getDao(UserVmDao.class); _vlanDao = locator.getDao(VlanDao.class); _volumeDao = locator.getDao(VolumeDao.class); + _site2SiteVpnGatewayDao = locator.getDao(Site2SiteVpnGatewayDao.class); + _site2SiteCustomerGatewayDao = locator.getDao(Site2SiteCustomerGatewayDao.class); _volumeHostDao = locator.getDao(VolumeHostDao.class); _zoneDao = locator.getDao(DataCenterDao.class); _securityGroupDao = locator.getDao(SecurityGroupDao.class); @@ -549,6 +557,14 @@ public class ApiDBUtils { return _volumeDao.findByIdIncludingRemoved(volumeId); } + public static Site2SiteVpnGatewayVO findVpnGatewayById(Long vpnGatewayId) { + return _site2SiteVpnGatewayDao.findById(vpnGatewayId); + } + + public static Site2SiteCustomerGatewayVO findCustomerGatewayById(Long customerGatewayId) { + return _site2SiteCustomerGatewayDao.findById(customerGatewayId); + } + public static List listUsersByAccount(long accountId) { return _userDao.listByAccount(accountId); } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 6477e536842..635119e5883 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -140,8 +140,10 @@ import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.network.RemoteAccessVpn; import com.cloud.network.Site2SiteCustomerGateway; +import com.cloud.network.Site2SiteCustomerGatewayVO; import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnGateway; +import com.cloud.network.Site2SiteVpnGatewayVO; import com.cloud.network.VirtualRouterProvider; import com.cloud.network.VpnUser; import com.cloud.network.router.VirtualRouter; @@ -3643,8 +3645,29 @@ public class ApiResponseHelper implements ResponseGenerator { public Site2SiteVpnConnectionResponse createSite2SiteVpnConnectionResponse(Site2SiteVpnConnection result) { Site2SiteVpnConnectionResponse response = new Site2SiteVpnConnectionResponse(); response.setId(result.getId()); - response.setVpnGatewayId(result.getVpnGatewayId()); - response.setCustomerGatewayId(result.getCustomerGatewayId()); + + response.setVpnGatewayId(result.getVpnGatewayId()); + Long vpnGatewayId = result.getVpnGatewayId(); + if(vpnGatewayId != null) { + Site2SiteVpnGatewayVO vpnGateway = ApiDBUtils.findVpnGatewayById(vpnGatewayId); + + long ipId = vpnGateway.getAddrId(); + IPAddressVO ipObj = ApiDBUtils.findIpAddressById(ipId); + response.setIp(ipObj.getAddress().addr()); + } + + response.setCustomerGatewayId(result.getCustomerGatewayId()); + Long customerGatewayId = result.getCustomerGatewayId(); + if(customerGatewayId != null) { + Site2SiteCustomerGatewayVO customerGateway = ApiDBUtils.findCustomerGatewayById(customerGatewayId); + response.setGatewayIp(customerGateway.getGatewayIp()); + response.setGuestCidrList(customerGateway.getGuestCidrList()); + response.setIpsecPsk(customerGateway.getIpsecPsk()); + response.setIkePolicy(customerGateway.getIkePolicy()); + response.setEspPolicy(customerGateway.getEspPolicy()); + response.setLifetime(customerGateway.getLifetime()); + } + response.setCreated(result.getCreated()); response.setRemoved(result.getRemoved()); response.setObjectName("vpnconnection"); diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 86a047c407a..7f4256fe6b2 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2132,6 +2132,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (network == null) { if (zone.getNetworkType() == DataCenter.NetworkType.Basic) { networkId = _networkMgr.getExclusiveGuestNetwork(zoneId).getId(); + network = _networkMgr.getNetwork(networkId); } else { network = _networkMgr.getNetworkWithSecurityGroupEnabled(zoneId); if (network == null) { diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index f5d51ed6f72..fc3124252b8 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1299,8 +1299,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.debug("Releasing ip id=" + addrId + "; sourceNat = " + ip.isSourceNat()); } + Network network = null; if (ip.getAssociatedWithNetworkId() != null) { - Network network = _networksDao.findById(ip.getAssociatedWithNetworkId()); + network = _networksDao.findById(ip.getAssociatedWithNetworkId()); + } + if (network != null) { try { if (!applyIpAssociations(network, true)) { s_logger.warn("Unable to apply ip address associations for " + network); @@ -1389,6 +1392,22 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.StaticNat, defaultProviders); defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.PortForwarding, defaultProviders); defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Vpn, defaultProviders); + + + Map> defaultVPCOffProviders = + new HashMap>(); + defaultProviders.clear(); + defaultProviders.add(Network.Provider.VirtualRouter); + defaultVPCOffProviders.put(Service.Dhcp, defaultProviders); + defaultVPCOffProviders.put(Service.Dns, defaultProviders); + defaultVPCOffProviders.put(Service.UserData, defaultProviders); + defaultVPCOffProviders.put(Service.NetworkACL, defaultProviders); + defaultVPCOffProviders.put(Service.Gateway, defaultProviders); + defaultVPCOffProviders.put(Service.Lb, defaultProviders); + defaultVPCOffProviders.put(Service.SourceNat, defaultProviders); + defaultVPCOffProviders.put(Service.StaticNat, defaultProviders); + defaultVPCOffProviders.put(Service.PortForwarding, defaultProviders); + defaultVPCOffProviders.put(Service.Vpn, defaultProviders); Transaction txn = Transaction.currentTxn(); txn.start(); @@ -1435,7 +1454,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks, "Offering for Isolated VPC networks with Source Nat service enabled", TrafficType.Guest, - null, false, Availability.Required, null, defaultIsolatedSourceNatEnabledNetworkOfferingProviders, + null, false, Availability.Required, null, defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false, null, false); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); @@ -2809,12 +2828,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { Vpc vpc = _vpcMgr.getActiveVpc(vpcId); - //1) Validate if network can be created for VPC - _vpcMgr.validateGuestNtkwForVpc(_configMgr.getNetworkOffering(ntwkOffId), cidr, networkDomain, owner, vpc); - if (networkDomain == null) { networkDomain = vpc.getNetworkDomain(); } + //1) Validate if network can be created for VPC + _vpcMgr.validateGuestNtkwForVpc(_configMgr.getNetworkOffering(ntwkOffId), cidr, networkDomain, owner, vpc, null); //2) Create network Network guestNetwork = createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, @@ -3716,7 +3734,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag handled = ((FirewallServiceProvider) ne).applyFWRules(network, rules); break; case NetworkACL: - boolean isNetworkACLProvider = isProviderSupportServiceInNetwork(network.getId(), Service.Firewall, provider); + boolean isNetworkACLProvider = isProviderSupportServiceInNetwork(network.getId(), Service.NetworkACL, provider); if (!(ne instanceof NetworkACLServiceProvider && isNetworkACLProvider)) { continue; } @@ -4540,7 +4558,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @DB @ActionEvent(eventType = EventTypes.EVENT_NETWORK_UPDATE, eventDescription = "updating network", async = true) - public Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix, Long networkOfferingId, Boolean changeCidr) { + public Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount, + User callerUser, String domainSuffix, Long networkOfferingId, Boolean changeCidr) { boolean restartNetwork = false; // verify input parameters @@ -4567,7 +4586,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (network.getTrafficType() != Networks.TrafficType.Guest) { throw new InvalidParameterValueException("Can't allow networks which traffic type is not " + TrafficType.Guest); } - + _accountMgr.checkAccess(callerAccount, null, true, network); if (name != null) { @@ -4594,13 +4613,19 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId"); throw ex; } - + // network offering should be in Enabled state if (networkOffering.getState() != NetworkOffering.State.Enabled) { InvalidParameterValueException ex = new InvalidParameterValueException("Network offering with specified id is not in " + NetworkOffering.State.Enabled + " state, can't upgrade to it"); ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId"); throw ex; } + + //perform below validation if the network is vpc network + if (network.getVpcId() != null) { + Vpc vpc = _vpcMgr.getVpc(network.getVpcId()); + _vpcMgr.validateGuestNtkwForVpc(networkOffering, null, null, null,vpc, networkId); + } if (networkOfferingId != oldNetworkOfferingId) { if (networkOfferingIsConfiguredForExternalNetworking(networkOfferingId) != networkOfferingIsConfiguredForExternalNetworking(oldNetworkOfferingId) @@ -6092,6 +6117,29 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.warn("Failed to cleanup firewall rules as a part of shutdownNetworkRules due to ", ex); success = false; } + + //revoke all Network ACLs for the network w/o applying them in the DB + List networkACLs = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.NetworkACL); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Releasing " + networkACLs.size() + " Network ACLs for network id=" + networkId + + " as a part of shutdownNetworkRules"); + } + + for (FirewallRuleVO networkACL : networkACLs) { + s_logger.trace("Marking network ACL " + networkACL + " with Revoke state"); + networkACL.setState(FirewallRule.State.Revoke); + } + + try { + if (!_firewallMgr.applyRules(networkACLs, true, false)) { + s_logger.warn("Failed to cleanup network ACLs as a part of shutdownNetworkRules"); + success = false; + } + } catch (ResourceUnavailableException ex) { + s_logger.warn("Failed to cleanup network ACLs as a part of shutdownNetworkRules due to ", ex); + success = false; + } + // Get all ip addresses, mark as releasing and release them on the backend Network network = getNetwork(networkId); diff --git a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index 1aa23daef4a..0473291d15d 100644 --- a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -266,7 +266,6 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp"); firewallCapabilities.put(Capability.MultipleIps, "true"); firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); - firewallCapabilities.put(Capability.FirewallType, "perpublicip"); capabilities.put(Service.Firewall, firewallCapabilities); // Disabling VPN for Juniper in Acton as it 1) Was never tested 2) probably just doesn't work diff --git a/server/src/com/cloud/network/element/NetscalerElement.java b/server/src/com/cloud/network/element/NetscalerElement.java index e8ea3bcdbe6..3febd9aaa64 100644 --- a/server/src/com/cloud/network/element/NetscalerElement.java +++ b/server/src/com/cloud/network/element/NetscalerElement.java @@ -270,7 +270,6 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); firewallCapabilities.put(Capability.MultipleIps, "true"); - firewallCapabilities.put(Capability.FirewallType, "perpublicip"); capabilities.put(Service.Firewall, firewallCapabilities); return capabilities; diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 05d8a99c02c..82b66d9f151 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -559,7 +559,6 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); firewallCapabilities.put(Capability.MultipleIps, "true"); - firewallCapabilities.put(Capability.FirewallType, "perpublicip"); capabilities.put(Service.Firewall, firewallCapabilities); // Set capabilities for vpn diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index 1b5c28861e5..b6f6d65340a 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -35,9 +35,9 @@ import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkService; import com.cloud.network.PublicIpAddress; -import com.cloud.network.VirtualRouterProvider.VirtualRouterProviderType; import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnGateway; +import com.cloud.network.VirtualRouterProvider.VirtualRouterProviderType; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.Site2SiteCustomerGatewayDao; import com.cloud.network.dao.Site2SiteVpnConnectionDao; @@ -112,9 +112,7 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc s_logger.trace("Element " + getProvider().getName() + " doesn't support service " + service.getName() + " in the network " + network); return false; - } else if (service == Service.Firewall) { - //todo - get capability here - } + } } return true; @@ -296,7 +294,8 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc } private static Map> setCapabilities() { - Map> capabilities = VirtualRouterElement.capabilities; + Map> capabilities = new HashMap>(); + capabilities.putAll(VirtualRouterElement.capabilities); Map sourceNatCapabilities = capabilities.get(Service.SourceNat); sourceNatCapabilities.put(Capability.RedundantRouter, "false"); @@ -306,10 +305,14 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc vpnCapabilities.put(Capability.VpnTypes, "s2svpn"); capabilities.put(Service.Vpn, vpnCapabilities); - Map firewallCapabilities = capabilities.get(Service.Firewall); - firewallCapabilities.put(Capability.FirewallType, "networkacl"); - capabilities.put(Service.Firewall, firewallCapabilities); - + //remove firewall capability + capabilities.remove(Service.Firewall); + + //add network ACL capability + Map networkACLCapabilities = new HashMap(); + networkACLCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); + capabilities.put(Service.NetworkACL, networkACLCapabilities); + return capabilities; } @@ -395,7 +398,7 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc @Override public boolean applyNetworkACLs(Network config, List rules) throws ResourceUnavailableException { - if (canHandle(config, Service.Firewall)) { + if (canHandle(config, Service.NetworkACL)) { List routers = _routerDao.listByNetworkAndRole(config.getId(), Role.VIRTUAL_ROUTER); if (routers == null || routers.isEmpty()) { s_logger.debug("Virtual router elemnt doesn't need to apply firewall rules on the backend; virtual " + diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index c4149680f65..f271edc1bf4 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -370,15 +370,6 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma if (!_elbEnabled) { caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.Lb); } - } else if (purpose == Purpose.Firewall) { - caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.Firewall); - if (caps != null) { - String firewallType = caps.get(Capability.FirewallType); - //regular firewall rules are not supported in networks supporting network ACLs - if (firewallType.equalsIgnoreCase("networkacl")) { - throw new UnsupportedOperationException("Firewall rules are not supported in network " + network); - } - } } else if (purpose == Purpose.PortForwarding) { caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.PortForwarding); } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 6bbc24cc546..4e40432cb63 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1188,7 +1188,14 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian //1) Get deployment plan and find out the list of routers boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic || _networkMgr.areServicesSupportedInNetwork(guestNetwork.getId(), Service.SecurityGroup)) - && guestNetwork.getTrafficType() == TrafficType.Guest; + && guestNetwork.getTrafficType() == TrafficType.Guest; + Long podId = null; + if (isPodBased) { + Pod pod = dest.getPod(); + if (pod != null) { + podId = pod.getId(); + } + } Pair> planAndRouters = getDeploymentPlanAndRouters(isPodBased, dest, guestNetwork.getId()); DeploymentPlan plan = planAndRouters.first(); List routers = planAndRouters.second(); @@ -1207,7 +1214,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian } /* If old network is redundant but new is single router, then routers.size() = 2 but routerCount = 1 */ - if (routers.size() >= routerCount || (isPodBased)) { + if (routers.size() >= routerCount || (isPodBased && podId == null)) { return routers; } diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 9de38537b66..47c64031450 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -27,7 +27,6 @@ import com.cloud.agent.AgentManager.OnError; import com.cloud.agent.api.GetDomRVersionCmd; import com.cloud.agent.api.PlugNicAnswer; import com.cloud.agent.api.PlugNicCommand; -import com.cloud.agent.api.SetSourceNatAnswer; import com.cloud.agent.api.SetupGuestNetworkAnswer; import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.UnPlugNicAnswer; @@ -79,11 +78,14 @@ import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.rules.NetworkACL; import com.cloud.network.vpc.NetworkACLManager; import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.PrivateIpAddress; +import com.cloud.network.vpc.PrivateIpVO; import com.cloud.network.vpc.StaticRoute; import com.cloud.network.vpc.StaticRouteProfile; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcGateway; import com.cloud.network.vpc.VpcManager; +import com.cloud.network.vpc.Dao.PrivateIpDao; import com.cloud.network.vpc.Dao.StaticRouteDao; import com.cloud.network.vpc.Dao.VpcDao; import com.cloud.network.vpc.Dao.VpcOfferingDao; @@ -126,6 +128,8 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian StaticRouteDao _staticRouteDao; @Inject VpcManager _vpcMgr; + @Inject + PrivateIpDao _privateIpDao; @Override public List deployVirtualRouterInVpc(Vpc vpc, DeployDestination dest, Account owner, @@ -373,7 +377,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian List publicIps = new ArrayList(1); publicIps.add(ipAddress); Commands cmds = new Commands(OnError.Stop); - createVpcAssociateIPCommands(router, publicIps, cmds); + createVpcAssociatePublicIPCommands(router, publicIps, cmds); if (sendCommandsToRouter(router, cmds)) { s_logger.debug("Successfully applied ip association for ip " + ipAddress + " in vpc network " + network); @@ -520,7 +524,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian return setupCmd; } - private void createVpcAssociateIPCommands(final VirtualRouter router, final List ips, + private void createVpcAssociatePublicIPCommands(final VirtualRouter router, final List ips, Commands cmds) { Pair sourceNatIpAdd = null; @@ -650,7 +654,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian @Override public boolean execute(Network network, VirtualRouter router) throws ResourceUnavailableException { Commands cmds = new Commands(OnError.Continue); - createVpcAssociateIPCommands(router, ipAddress, cmds); + createVpcAssociatePublicIPCommands(router, ipAddress, cmds); return sendCommandsToRouter(router, cmds); } }); @@ -805,32 +809,31 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian // create ip assoc for source nat if (!sourceNat.isEmpty()) { - createVpcAssociateIPCommands(router, sourceNat, cmds); + createVpcAssociatePublicIPCommands(router, sourceNat, cmds); } - for (Nic guestNic : guestNics.keySet()) { + for (Nic nic : guestNics.keySet()) { //plug guest nic - PlugNicCommand plugNicCmd = new PlugNicCommand(_itMgr.toVmTO(profile), getNicTO(router, guestNic.getNetworkId())); + PlugNicCommand plugNicCmd = new PlugNicCommand(_itMgr.toVmTO(profile), getNicTO(router, nic.getNetworkId())); cmds.addCommand(plugNicCmd); - if (!_networkMgr.isPrivateGateway(guestNic)) { + if (!_networkMgr.isPrivateGateway(nic)) { //set guest network VirtualMachine vm = _vmDao.findById(router.getId()); - NicProfile nicProfile = _networkMgr.getNicProfile(vm, guestNic.getNetworkId()); + NicProfile nicProfile = _networkMgr.getNicProfile(vm, nic.getNetworkId()); SetupGuestNetworkCommand setupCmd = createSetupGuestNetworkCommand(router, true, nicProfile); cmds.addCommand(setupCmd); } else { - //set source nat - Integer networkRate = _networkMgr.getNetworkRate(guestNic.getNetworkId(), router.getId()); - IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, guestNic.getIp4Address(), true, false, - true, guestNic.getBroadcastUri().getHost(), guestNic.getGateway(), guestNic.getNetmask(), guestNic.getMacAddress(), - null, networkRate, false); - Network network = _networkMgr.getNetwork(guestNic.getNetworkId()); - ip.setTrafficType(network.getTrafficType()); - SetSourceNatCommand cmd = new SetSourceNatCommand(ip, true); - cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); - cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); - cmds.addCommand(cmd); + //set private network + PrivateIpVO ipVO = _privateIpDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIp4Address()); + Network network = _networkDao.findById(nic.getNetworkId()); + String vlanTag = network.getBroadcastUri().getHost(); + String netmask = NetUtils.getCidrNetmask(network.getCidr()); + PrivateIpAddress ip = new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, ipVO.getMacAddress()); + + List privateIps = new ArrayList(1); + privateIps.add(ip); + createVpcAssociatePrivateIPCommands(router, privateIps, cmds, true); } } } catch (Exception ex) { @@ -894,7 +897,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian super.finalizeNetworkRulesForNetwork(cmds, router, provider, guestNetworkId); - if (_networkMgr.isProviderSupportServiceInNetwork(guestNetworkId, Service.Firewall, Provider.VPCVirtualRouter)) { + if (_networkMgr.isProviderSupportServiceInNetwork(guestNetworkId, Service.NetworkACL, Provider.VPCVirtualRouter)) { List networkACLs = _networkACLMgr.listNetworkACLs(guestNetworkId); s_logger.debug("Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + router + " start for guest network id=" + guestNetworkId); @@ -943,32 +946,25 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian */ protected boolean setupVpcPrivateNetwork(VirtualRouter router, boolean add, NicProfile privateNic) throws AgentUnavailableException { - boolean result = true; + + PrivateIpVO ipVO = _privateIpDao.findByIpAndSourceNetworkId(privateNic.getNetworkId(), privateNic.getIp4Address()); + Network network = _networkDao.findById(privateNic.getNetworkId()); + String vlanTag = network.getBroadcastUri().getHost(); + String netmask = NetUtils.getCidrNetmask(network.getCidr()); + PrivateIpAddress ip = new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, ipVO.getMacAddress()); + + List privateIps = new ArrayList(1); + privateIps.add(ip); Commands cmds = new Commands(OnError.Stop); + createVpcAssociatePrivateIPCommands(router, privateIps, cmds, add); - Integer networkRate = _networkMgr.getNetworkRate(privateNic.getNetworkId(), router.getId()); - IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, privateNic.getIp4Address(), add, false, - true, privateNic.getBroadCastUri().getHost(), privateNic.getGateway(), privateNic.getNetmask(), privateNic.getMacAddress(), - null, networkRate, false); - Network network = _networkMgr.getNetwork(privateNic.getNetworkId()); - ip.setTrafficType(network.getTrafficType()); - - SetSourceNatCommand cmd = new SetSourceNatCommand(ip, add); - cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); - cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); - DataCenterVO dcVo = _dcDao.findById(router.getDataCenterIdToDeployIn()); - cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString()); - cmds.addCommand("SetSourceNatCommand", cmd); - sendCommandsToRouter(router, cmds); - - SetSourceNatAnswer setupAnswer = cmds.getAnswer(SetSourceNatAnswer.class); - String setup = add ? "set" : "destroy"; - if (!(setupAnswer != null && setupAnswer.getResult())) { - s_logger.warn("Unable to " + setup + " source nat for private gateway " + privateNic + " on router " + router); - result = false; - } - - return result; + if (sendCommandsToRouter(router, cmds)) { + s_logger.debug("Successfully applied ip association for ip " + ip + " in vpc network " + network); + return true; + } else { + s_logger.warn("Failed to associate ip address " + ip + " in vpc network " + network); + return false; + } } @Override @@ -1005,9 +1001,8 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian if (publicIps != null && !publicIps.isEmpty()) { s_logger.debug("Found " + publicIps.size() + " ip(s) to apply as a part of domR " + router + " start."); // Re-apply public ip addresses - should come before PF/LB/VPN - if (_networkMgr.isProviderSupportServiceInNetwork(guestNetworkId, Service.Firewall, provider)) { - createVpcAssociateIPCommands(router, publicIps, cmds); - } + createVpcAssociatePublicIPCommands(router, publicIps, cmds); + } } @@ -1084,4 +1079,47 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString()); cmds.addCommand("applyS2SVpn", cmd); } + + private void createVpcAssociatePrivateIPCommands(final VirtualRouter router, final List ips, + Commands cmds, boolean add) { + + // Ensure that in multiple vlans case we first send all ip addresses of vlan1, then all ip addresses of vlan2, etc.. + Map> vlanIpMap = new HashMap>(); + for (final PrivateIpAddress ipAddress : ips) { + String vlanTag = ipAddress.getVlanTag(); + ArrayList ipList = vlanIpMap.get(vlanTag); + if (ipList == null) { + ipList = new ArrayList(); + } + + ipList.add(ipAddress); + vlanIpMap.put(vlanTag, ipList); + } + + for (Map.Entry> vlanAndIp : vlanIpMap.entrySet()) { + List ipAddrList = vlanAndIp.getValue(); + IpAddressTO[] ipsToSend = new IpAddressTO[ipAddrList.size()]; + int i = 0; + + for (final PrivateIpAddress ipAddr : ipAddrList) { + Network network = _networkMgr.getNetwork(ipAddr.getNetworkId()); + IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, ipAddr.getIpAddress(), add, false, + false, ipAddr.getVlanTag(), ipAddr.getGateway(), ipAddr.getNetmask(), ipAddr.getMacAddress(), + null, null, false); + + ip.setTrafficType(network.getTrafficType()); + ip.setNetworkName(_networkMgr.getNetworkTag(router.getHypervisorType(), network)); + ipsToSend[i++] = ip; + + } + IpAssocVpcCommand cmd = new IpAssocVpcCommand(ipsToSend); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, getRouterIpInNetwork(ipAddrList.get(0).getNetworkId(), router.getId())); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); + DataCenterVO dcVo = _dcDao.findById(router.getDataCenterIdToDeployIn()); + cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString()); + + cmds.addCommand("IPAssocVpcCommand", cmd); + } + } } diff --git a/server/src/com/cloud/network/vpc/Dao/VpcOfferingDaoImpl.java b/server/src/com/cloud/network/vpc/Dao/VpcOfferingDaoImpl.java index b5e6c6ede8a..ac6ebe7fbfb 100644 --- a/server/src/com/cloud/network/vpc/Dao/VpcOfferingDaoImpl.java +++ b/server/src/com/cloud/network/vpc/Dao/VpcOfferingDaoImpl.java @@ -30,7 +30,6 @@ import com.cloud.utils.db.Transaction; public class VpcOfferingDaoImpl extends GenericDaoBase implements VpcOfferingDao{ final SearchBuilder AllFieldsSearch; - protected VpcOfferingDaoImpl() { super(); diff --git a/server/src/com/cloud/network/vpc/Dao/VpcOfferingServiceMapDao.java b/server/src/com/cloud/network/vpc/Dao/VpcOfferingServiceMapDao.java index af896220da9..d9ef8a27c9f 100644 --- a/server/src/com/cloud/network/vpc/Dao/VpcOfferingServiceMapDao.java +++ b/server/src/com/cloud/network/vpc/Dao/VpcOfferingServiceMapDao.java @@ -33,5 +33,7 @@ public interface VpcOfferingServiceMapDao extends GenericDao listServicesForVpcOffering(long vpcOfferingId); + + VpcOfferingServiceMapVO findByServiceProviderAndOfferingId(String service, String provider, long vpcOfferingId); } diff --git a/server/src/com/cloud/network/vpc/Dao/VpcOfferingServiceMapDaoImpl.java b/server/src/com/cloud/network/vpc/Dao/VpcOfferingServiceMapDaoImpl.java index 9fbc1fff556..40aece75fe7 100644 --- a/server/src/com/cloud/network/vpc/Dao/VpcOfferingServiceMapDaoImpl.java +++ b/server/src/com/cloud/network/vpc/Dao/VpcOfferingServiceMapDaoImpl.java @@ -101,4 +101,15 @@ public class VpcOfferingServiceMapDaoImpl extends GenericDaoBase sc = AllFieldsSearch.create(); + sc.setParameters("vpcOffId", vpcOfferingId); + sc.setParameters("service", service); + sc.setParameters("provider", provider); + + return findOneBy(sc); + } } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index 6e3ba66e21c..985f7145ad8 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -138,8 +138,8 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLManager{ _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network); - if (!_networkMgr.areServicesSupportedInNetwork(networkId, Service.Firewall)) { - throw new InvalidParameterValueException("Service " + Service.Firewall + " is not supported in network " + network); + if (!_networkMgr.areServicesSupportedInNetwork(networkId, Service.NetworkACL)) { + throw new InvalidParameterValueException("Service " + Service.NetworkACL + " is not supported in network " + network); } // icmp code and icmp type can't be passed in for any other protocol rather than icmp @@ -153,7 +153,6 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLManager{ validateNetworkACL(caller, network, portStart, portEnd, protocol); - Transaction txn = Transaction.currentTxn(); txn.start(); @@ -198,7 +197,7 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLManager{ } // Verify that the network guru supports the protocol specified - Map caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.Firewall); + Map caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.NetworkACL); if (caps != null) { @@ -206,11 +205,6 @@ public class NetworkACLManagerImpl implements Manager,NetworkACLManager{ if (!supportedProtocols.contains(proto.toLowerCase())) { throw new InvalidParameterValueException("Protocol " + proto + " is not supported by the network " + network); } - - String firewallType = caps.get(Capability.FirewallType); - if (!firewallType.equalsIgnoreCase("networkacl")) { - throw new UnsupportedOperationException("Network ACLS are not supported in network " + network); - } } else { throw new InvalidParameterValueException("No capabilities are found for network " + network); } diff --git a/server/src/com/cloud/network/vpc/PrivateIpAddress.java b/server/src/com/cloud/network/vpc/PrivateIpAddress.java index 7a568c17157..a1755e024c7 100644 --- a/server/src/com/cloud/network/vpc/PrivateIpAddress.java +++ b/server/src/com/cloud/network/vpc/PrivateIpAddress.java @@ -23,6 +23,7 @@ public class PrivateIpAddress implements PrivateIp{ String netmask; String ipAddress; String macAddress; + long networkId; /** * @param privateIp @@ -39,6 +40,7 @@ public class PrivateIpAddress implements PrivateIp{ this.gateway = gateway; this.netmask = netmask; this.macAddress = NetUtils.long2Mac(macAddress); + this.networkId = privateIp.getNetworkId(); } @Override @@ -65,4 +67,9 @@ public class PrivateIpAddress implements PrivateIp{ public String getMacAddress() { return macAddress; } + + @Override + public long getNetworkId() { + return networkId; + } } diff --git a/server/src/com/cloud/network/vpc/PrivateIpVO.java b/server/src/com/cloud/network/vpc/PrivateIpVO.java index 48397559cfd..b9f31429d66 100644 --- a/server/src/com/cloud/network/vpc/PrivateIpVO.java +++ b/server/src/com/cloud/network/vpc/PrivateIpVO.java @@ -29,7 +29,7 @@ import javax.persistence.TemporalType; @Entity @Table(name="private_ip_address") -public class PrivateIpVO { +public class PrivateIpVO{ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @@ -65,7 +65,7 @@ public class PrivateIpVO { public String getIpAddress() { return ipAddress; } - + public long getNetworkId() { return networkId; } diff --git a/server/src/com/cloud/network/vpc/VpcManager.java b/server/src/com/cloud/network/vpc/VpcManager.java index 55a607f2779..e42bf84961a 100644 --- a/server/src/com/cloud/network/vpc/VpcManager.java +++ b/server/src/com/cloud/network/vpc/VpcManager.java @@ -70,11 +70,11 @@ public interface VpcManager extends VpcService{ * @param networkDomain * @param networkOwner * @param vpc TODO + * @param networkId TODO * @return - * @throws ConcurrentOperationException */ void validateGuestNtkwForVpc(NetworkOffering guestNtwkOff, String cidr, String networkDomain, Account networkOwner, - Vpc vpc) throws ConcurrentOperationException; + Vpc vpc, Long networkId); /** * @return diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index ab658980ae5..12529134032 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -65,6 +65,7 @@ import com.cloud.network.vpc.Dao.VpcGatewayDao; import com.cloud.network.vpc.Dao.VpcOfferingDao; import com.cloud.network.vpc.Dao.VpcOfferingServiceMapDao; import com.cloud.offering.NetworkOffering; +import com.cloud.offerings.NetworkOfferingServiceMapVO; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.org.Grouping; import com.cloud.projects.Project.ListProjectResourcesCriteria; @@ -129,6 +130,8 @@ public class VpcManagerImpl implements VpcManager, Manager{ StaticRouteDao _staticRouteDao; @Inject NetworkOfferingServiceMapDao _ntwkOffServiceDao ; + @Inject + VpcOfferingServiceMapDao _vpcOffServiceDao; private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker")); @@ -150,10 +153,17 @@ public class VpcManagerImpl implements VpcManager, Manager{ s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName); Map> svcProviderMap = new HashMap>(); - Set provider = new HashSet(); - provider.add(Provider.VPCVirtualRouter); + Set defaultProviders = new HashSet(); + defaultProviders.add(Provider.VPCVirtualRouter); for (Service svc : getSupportedServices()) { - svcProviderMap.put(svc, provider); + if (svc == Service.Lb) { + Set lbProviders = new HashSet(); + lbProviders.add(Provider.VPCVirtualRouter); + lbProviders.add(Provider.Netscaler); + svcProviderMap.put(svc, lbProviders); + } else { + svcProviderMap.put(svc, defaultProviders); + } } createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, true, State.Enabled); @@ -218,6 +228,13 @@ public class VpcManagerImpl implements VpcManager, Manager{ throw new UnsupportedServiceException("Service " + Service.SecurityGroup.getName() + " is not supported by VPC"); } svcProviderMap.put(service, defaultProviders); + if (service == Service.NetworkACL) { + firewallSvs = true; + } + + if (service == Service.SourceNat) { + sourceNatSvc = true; + } } if (!sourceNatSvc) { @@ -226,8 +243,8 @@ public class VpcManagerImpl implements VpcManager, Manager{ } if (!firewallSvs) { - s_logger.debug("Automatically adding firewall service to the list of VPC services"); - svcProviderMap.put(Service.Firewall, defaultProviders); + s_logger.debug("Automatically adding network ACL service to the list of VPC services"); + svcProviderMap.put(Service.NetworkACL, defaultProviders); } svcProviderMap.put(Service.Gateway, defaultProviders); @@ -716,7 +733,7 @@ public class VpcManagerImpl implements VpcManager, Manager{ services.add(Network.Service.Dhcp); services.add(Network.Service.Dns); services.add(Network.Service.UserData); - services.add(Network.Service.Firewall); + services.add(Network.Service.NetworkACL); services.add(Network.Service.PortForwarding); services.add(Network.Service.Lb); services.add(Network.Service.SourceNat); @@ -814,11 +831,66 @@ public class VpcManagerImpl implements VpcManager, Manager{ @Override @DB public void validateGuestNtkwForVpc(NetworkOffering guestNtwkOff, String cidr, String networkDomain, - Account networkOwner, Vpc vpc) throws ConcurrentOperationException { + Account networkOwner, Vpc vpc, Long networkId) { + if (networkId == null) { + //1) Validate attributes that has to be passed in when create new guest network + validateNewVpcGuestNetwork(cidr, networkOwner, vpc, networkDomain); + } + + //2) Only Isolated networks with Source nat service enabled can be added to vpc + if (!(guestNtwkOff.getGuestType() == GuestType.Isolated + && _ntwkMgr.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.SourceNat))) { + + throw new InvalidParameterValueException("Only networks of type " + GuestType.Isolated + " with service " + + Service.SourceNat + + " can be added as a part of VPC"); + } + + //3) No redundant router support + if (guestNtwkOff.getRedundantRouter()) { + throw new InvalidParameterValueException("No redunant router support when network belnogs to VPC"); + } + + //4) Conserve mode should be off + if (guestNtwkOff.isConserveMode()) { + throw new InvalidParameterValueException("Only networks with conserve mode Off can belong to VPC"); + } + + //5) Check services/providers against VPC providers + List networkProviders = _ntwkOffServiceDao.listByNetworkOfferingId(guestNtwkOff.getId()); + + for (NetworkOfferingServiceMapVO nSvcVO : networkProviders) { + String pr = nSvcVO.getProvider(); + String service = nSvcVO.getService(); + if (_vpcOffServiceDao.findByServiceProviderAndOfferingId(service, pr, vpc.getVpcOfferingId()) == null) { + throw new InvalidParameterValueException("Service/provider combination " + service + "/" + + pr + " is not supported by VPC " + vpc); + } + } + + //6) Only one network in the VPC can support LB + if (_ntwkMgr.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.Lb)) { + List networks = getVpcNetworks(vpc.getId()); + for (Network network : networks) { + if (networkId != null && network.getId() == networkId.longValue()) { + //skip my own network + continue; + } else { + if (_ntwkMgr.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { + throw new InvalidParameterValueException("LB service is already supported " + + "by network " + network + " in VPC " + vpc); + } + } + } + } + + } + + protected void validateNewVpcGuestNetwork(String cidr, Account networkOwner, Vpc vpc, String networkDomain) { Vpc locked = _vpcDao.acquireInLockTable(vpc.getId()); if (locked == null) { - throw new ConcurrentOperationException("Unable to acquire lock on " + vpc); + throw new CloudRuntimeException("Unable to acquire lock on " + vpc); } try { @@ -846,45 +918,14 @@ public class VpcManagerImpl implements VpcManager, Manager{ //4) vpc and network should belong to the same owner if (vpc.getAccountId() != networkOwner.getId()) { throw new InvalidParameterValueException("Vpc " + vpc + " owner is different from the network owner " - + networkOwner); + + networkOwner); } - //5) Only Isolated networks with Source nat service enabled can be added to vpc - if (!(guestNtwkOff.getGuestType() == GuestType.Isolated - && _ntwkMgr.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.SourceNat))) { - - throw new InvalidParameterValueException("Only networks of type " + GuestType.Isolated + " with service " - + Service.SourceNat + - " can be added as a part of VPC"); + //5) network domain should be the same as VPC's + if (!networkDomain.equalsIgnoreCase(vpc.getNetworkDomain())) { + throw new InvalidParameterValueException("Network domain of the new network should match network" + + " domain of vpc " + vpc); } - - //6) Only VPC VR can be a provider for the network offering - List ntwkOffProviders = _ntwkMgr.getNtwkOffDistinctProviders(guestNtwkOff.getId()); - for (Provider provider : ntwkOffProviders) { - if (provider != Provider.VPCVirtualRouter) { - throw new InvalidParameterValueException("Only VPCVirtualRouter provider is supported in VPC network;" + - " while network offering " + guestNtwkOff + " has " + provider.getName() + " enabled."); - } - } - - //7) No redundant router support - if (guestNtwkOff.getRedundantRouter()) { - throw new InvalidParameterValueException("No redunant router support when network belnogs to VPC"); - } - - //8) Conserve mode should be off - if (guestNtwkOff.isConserveMode()) { - throw new InvalidParameterValueException("Only networks with conserve mode Off can belong to VPC"); - } - - //9) list supported services should be within VPC supported services - List ntwkOffServices = _ntwkOffServiceDao.listServicesForNetworkOffering(guestNtwkOff.getId()); - List vpcOffServices = _vpcOffSvcMapDao.listServicesForVpcOffering(vpc.getVpcOfferingId()); - - if (!vpcOffServices.containsAll(ntwkOffServices)) { - throw new InvalidParameterValueException("VPC doesn't support some of the services specified in the network offering"); - } - } finally { s_logger.debug("Releasing lock for " + locked); _vpcDao.releaseFromLockTable(locked.getId()); diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java index 6c41ec8cacf..0104d09c27a 100644 --- a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java @@ -145,6 +145,8 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnService, Manager { + vpnGatewayId + " already existed!"); } Site2SiteVpnConnectionVO conn = new Site2SiteVpnConnectionVO(vpnGatewayId, customerGatewayId); + conn.setState(State.Pending); + _vpnConnectionDao.persist(conn); return conn; } diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 1560fd1e26e..4f7a16347e3 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -1030,7 +1030,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { defaultVpcNetworkOfferingProviders.put(Service.Dhcp, Provider.VPCVirtualRouter); defaultVpcNetworkOfferingProviders.put(Service.Dns, Provider.VPCVirtualRouter); defaultVpcNetworkOfferingProviders.put(Service.UserData, Provider.VPCVirtualRouter); - defaultVpcNetworkOfferingProviders.put(Service.Firewall, Provider.VPCVirtualRouter); + defaultVpcNetworkOfferingProviders.put(Service.NetworkACL, Provider.VPCVirtualRouter); defaultVpcNetworkOfferingProviders.put(Service.Gateway, Provider.VPCVirtualRouter); defaultVpcNetworkOfferingProviders.put(Service.Lb, Provider.VPCVirtualRouter); defaultVpcNetworkOfferingProviders.put(Service.SourceNat, Provider.VPCVirtualRouter); diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js index 9b565c62d90..525ee5947f4 100644 --- a/ui/scripts/accounts.js +++ b/ui/scripts/accounts.js @@ -173,7 +173,7 @@ action: function(args) { var array1 = []; array1.push("&username=" + todb(args.data.username)); - + var errorMsg = ""; var password = args.data.password; if (md5Hashed) password = $.md5(password); @@ -262,6 +262,7 @@ edit: { label: 'message.edit.account', action: function(args) { + var errorMsg = ""; var accountObj = args.context.accounts[0]; var array1 = []; @@ -273,7 +274,12 @@ async: false, success: function(json) { accountObj = json.updateaccountresponse.account; + }, + error: function(json) { + errorMsg = parseXMLHttpResponse(json); + args.response.error(errorMsg); } + }); $.ajax({ @@ -321,6 +327,7 @@ } }); + if(errorMsg == "") args.response.success({data: accountObj}); } }, diff --git a/ui/scripts/network.js b/ui/scripts/network.js index d0a77dd5ea0..af61a18b201 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -3195,11 +3195,13 @@ listView: { id: 'siteToSiteVpn', label: 'site-to-site VPN', - fields: { - id: { label: 'label.id' }, - s2svpngatewayid: { label: 's2svpngatewayid' }, - s2scustomergatewayid: { label: 's2scustomergatewayid' }, - created: { label: 'label.date', converter: cloudStack.converters.toLocalDate } + fields: { + publicip: { label: 'label.ip.address' }, + gateway: { label: 'label.gateway' }, + cidrlist: { label: 'CIDR list' }, + ipsecpsk: { label: 'IPsec Preshared-Key' }, + ikepolicy: { label: 'IKE policy' }, + esppolicy: { label: 'ESP policy' } }, dataProvider: function(args) { var array1 = []; @@ -3299,7 +3301,7 @@ } }, lifetime: { - label: 'Lifetime of vpn connection (second)', + label: 'Lifetime (second)', defaultValue: '86400', validation: { required: false, number: true } } @@ -3376,18 +3378,28 @@ return; //Job has not completed } else { - clearInterval(createvpnconnectionIntervalID); - if (result.jobstatus == 1) { - var obj = result.jobresult.vpnconnection; + clearInterval(createvpnconnectionIntervalID); + + if (result.jobstatus == 1) { + //remove loading image on table row + var $listviewTable = $("div.list-view div.data-table table.body tbody"); + var $tr1 = $listviewTable.find("tr.loading").removeClass("loading"); + $tr1.find("td div.loading").removeClass("loading"); + + var item = result.jobresult.vpnconnection; + $tr1.find("td.publicip span").text(item.publicip); + + cloudStack.dialog.notice({ message: "site-to-site VPN is created successfully." }); } else if (result.jobstatus == 2) { - alert("Failed to create VPN connection. Error: " + _s(result.jobresult.errortext)); + $.removeTableRowInAction(); + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); } } }, error: function(XMLHttpResponse) { - var errorMsg = parseXMLHttpResponse(XMLHttpResponse); - alert("Failed to create VPN connection. Error: " + errorMsg); + $.removeTableRowInAction(); + cloudStack.dialog.notice({ message: parseXMLHttpResponse(XMLHttpResponse) }); } }); }, 3000); @@ -3395,27 +3407,29 @@ }); } else if (result.jobstatus == 2) { - alert("Failed to create VPN customer gateway. Error: " + _s(result.jobresult.errortext)); + $.removeTableRowInAction(); + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); } } }, error: function(XMLHttpResponse) { - var errorMsg = parseXMLHttpResponse(XMLHttpResponse); - alert("Failed to create VPN customer gateway. Error: " + errorMsg); + $.removeTableRowInAction(); + cloudStack.dialog.notice({ message: parseXMLHttpResponse(XMLHttpResponse) }); } }); }, 3000); } }); } - else if (result.jobstatus == 2) { - alert("Failed to create VPN gateway. Error: " + _s(result.jobresult.errortext)); + else if (result.jobstatus == 2) { + $.removeTableRowInAction(); + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); } } }, - error: function(XMLHttpResponse) { - var errorMsg = parseXMLHttpResponse(XMLHttpResponse); - alert("Failed to create VPN gateway. Error: " + errorMsg); + error: function(XMLHttpResponse) { + $.removeTableRowInAction(); + cloudStack.dialog.notice({ message: parseXMLHttpResponse(XMLHttpResponse) }); } }); }, 3000); @@ -3431,11 +3445,21 @@ details: { title: 'label.details', fields: [ - { - id: { label: 'label.id' }, - s2svpngatewayid: { label: 's2svpngatewayid' }, - s2scustomergatewayid: { label: 's2scustomergatewayid' }, - created: { label: 'label.date', converter: cloudStack.converters.toLocalDate } + { + id: { label: 'label.id' }, + + //s2svpngatewayid: { label: 'VPN gateway ID' }, + publicip: { label: 'label.ip.address' }, + + //s2scustomergatewayid: { label: 'Customer gateway ID' }, + gateway: { label: 'label.gateway' }, + cidrlist: { label: 'CIDR list' }, + ipsecpsk: { label: 'IPsec Preshared-Key' }, + ikepolicy: { label: 'IKE policy' }, + esppolicy: { label: 'ESP policy' }, + lifetime: { label: 'Lifetime (second)' }, + + created: { label: 'label.date', converter: cloudStack.converters.toLocalDate } } ], dataProvider: function(args) { @@ -3450,7 +3474,133 @@ }); } } - } + }, + actions: { + remove: { + label: 'delete site-to-site VPN', + messages: { + confirm: function(args) { + return 'Please confirm that you want to delete this site-to-site VPN'; + }, + notification: function(args) { + return 'delete site-to-site VPN'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteVpnConnection"), + dataType: "json", + data: { + id: args.context.siteToSiteVpn[0].id + }, + async: true, + success: function(json) { + var jid = json.deletevpnconnectionresponse.jobid; + var deleteVpnConnectionIntervalID = setInterval(function() { + $.ajax({ + url: createURL("queryAsyncJobResult&jobId=" + jid), + dataType: "json", + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } + else { + clearInterval(deleteVpnConnectionIntervalID); + if (result.jobstatus == 1) { + $.ajax({ + url: createURL("deleteVpnGateway"), + dataType: "json", + data: { + id: args.context.siteToSiteVpn[0].s2svpngatewayid + }, + async: true, + success: function(json) { + var jid = json.deletevpngatewayresponse.jobid; + var deleteVpnGatewayIntervalID = setInterval(function() { + $.ajax({ + url: createURL("queryAsyncJobResult&jobId=" + jid), + dataType: "json", + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } + else { + clearInterval(deleteVpnGatewayIntervalID); + if (result.jobstatus == 1) { + $.ajax({ + url: createURL("deleteVpnCustomerGateway"), + dataType: "json", + data: { + id: args.context.siteToSiteVpn[0].s2scustomergatewayid + }, + async: true, + success: function(json) { + var jid = json.deletecustomergatewayresponse.jobid; + var deleteVpnCustomerGatewayIntervalID = setInterval(function() { + $.ajax({ + url: createURL("queryAsyncJobResult&jobId=" + jid), + dataType: "json", + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } + else { + clearInterval(deleteVpnCustomerGatewayIntervalID); + if (result.jobstatus == 1) { + $("div.detail-view div.loading-overlay").remove(); + cloudStack.dialog.notice({ message: "site-to-site VPN has been deleted." }); + $.removeDetailViewAndTableRow(); + } + else if (result.jobstatus == 2) { + $("div.detail-view div.loading-overlay").remove(); + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); + } + } + }, + error: function(XMLHttpResponse) { + $("div.detail-view div.loading-overlay").remove(); + cloudStack.dialog.notice({ message: parseXMLHttpResponse(XMLHttpResponse) }); + } + }); + }, 3000); + } + }); + } + else if (result.jobstatus == 2) { + $("div.detail-view div.loading-overlay").remove(); + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); + } + } + }, + error: function(XMLHttpResponse) { + $("div.detail-view div.loading-overlay").remove(); + cloudStack.dialog.notice({ message: parseXMLHttpResponse(XMLHttpResponse) }); + } + }); + }, 3000); + } + }); + } + else if (result.jobstatus == 2) { + $("div.detail-view div.loading-overlay").remove(); + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); + } + } + }, + error: function(XMLHttpResponse) { + $("div.detail-view div.loading-overlay").remove(); + cloudStack.dialog.notice({ message: parseXMLHttpResponse(XMLHttpResponse) }); + } + }); + }, 3000); + } + }); + } + } + } } } } diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 1c95928721c..7911228e8ff 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -55,6 +55,7 @@ var pollAsyncJobResult = function(args) { } else { if (result.jobstatus == 1) { // Succeeded + debugger; if(args._custom.getUpdatedItem != null && args._custom.getActionFilter != null) { args.complete({ data: args._custom.getUpdatedItem(json), @@ -276,6 +277,32 @@ cloudStack.actionFilter = { } } +$.removeTableRowInAction = function() { //remove table row that has loading image on top of it (i.e. table row that is in action) (e.g. after add action in listView succeeds) + var $listviewTable = $("div.list-view div.data-table table.body tbody"); + var $tr1 = $listviewTable.find("tr.loading").removeClass("loading"); + $tr1.find("td div.loading").removeClass("loading"); + $tr1.remove(); + if($listviewTable.find("tr").length == 0) + $listviewTable.append($("").addClass("empty even").append($("").text("No data to show"))); +} + +$.removeDetailViewAndTableRow = function() { //remove detail view and corresponding table row (e.g. after remove action in detailView succeeds) + var $detailView = $("div.detail-view"); + var $panel = $detailView.closest('.panel'); + var $browser = $('#browser .container'); + if ($detailView.is(':visible')) { + $browser.cloudBrowser('selectPanel', { + panel: $panel.prev() + }); + } + if($detailView.data("list-view-row") != null) { + $detailView.data("list-view-row").remove(); + var $listviewTable = $("div.list-view div.data-table table.body tbody"); + if($listviewTable.find("tr").length == 0) + $listviewTable.append($("").addClass("empty even").append($("").text("No data to show"))); + } +} + var roleTypeUser = "0"; var roleTypeAdmin = "1"; var roleTypeDomainAdmin = "2"; diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index 769631c68d8..a51c815f4ae 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -1306,7 +1306,7 @@ allowedActions.push("recurringSnapshot"); } if(jsonObj.state != "Allocated") { - if((jsonObj.vmstate == "Stopped" || jsonObj.virtualmachineid == null) && jsonObj.state !="Ready") { + if((jsonObj.vmstate == "Stopped" || jsonObj.virtualmachineid == null) && jsonObj.state != "Ready") { allowedActions.push("downloadVolume"); } }