diff --git a/api/src/com/cloud/api/response/NicResponse.java b/api/src/com/cloud/api/response/NicResponse.java index 53793f16c31..01d6d3b3740 100755 --- a/api/src/com/cloud/api/response/NicResponse.java +++ b/api/src/com/cloud/api/response/NicResponse.java @@ -26,6 +26,9 @@ public class NicResponse extends BaseResponse { @SerializedName("networkid") @Param(description="the ID of the corresponding network") private final IdentityProxy networkId = new IdentityProxy("networks"); + @SerializedName("networkname") @Param(description="the name of the corresponding network") + private String networkName ; + @SerializedName(ApiConstants.NETMASK) @Param(description="the netmask of the nic") private String netmask; @@ -65,6 +68,10 @@ public class NicResponse extends BaseResponse { this.networkId.setValue(networkid); } + public void setNetworkName(String networkname) { + this.networkName = networkname; + } + public void setNetmask(String netmask) { this.netmask = netmask; } diff --git a/api/src/com/cloud/api/response/Site2SiteCustomerGatewayResponse.java b/api/src/com/cloud/api/response/Site2SiteCustomerGatewayResponse.java index b0a90c9d81e..0b5d286dce6 100644 --- a/api/src/com/cloud/api/response/Site2SiteCustomerGatewayResponse.java +++ b/api/src/com/cloud/api/response/Site2SiteCustomerGatewayResponse.java @@ -39,6 +39,15 @@ public class Site2SiteCustomerGatewayResponse extends BaseResponse implements Co @SerializedName(ApiConstants.IPSEC_PSK) @Param(description="IPsec preshared-key of customer gateway") private String ipsecPsk; + @SerializedName(ApiConstants.IKE_POLICY) @Param(description="IKE policy of customer gateway") + private String ikePolicy; + + @SerializedName(ApiConstants.ESP_POLICY) @Param(description="IPsec policy of customer gateway") + private String espPolicy; + + @SerializedName(ApiConstants.LIFETIME) @Param(description="Lifetime of IKE and IPsec policy of customer gateway") + private Long lifetime; + @SerializedName(ApiConstants.ACCOUNT) @Param(description="the owner") private String accountName; @@ -81,6 +90,18 @@ public class Site2SiteCustomerGatewayResponse extends BaseResponse implements Co 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 setRemoved(Date removed) { this.removed = removed; } diff --git a/api/src/com/cloud/network/Site2SiteCustomerGateway.java b/api/src/com/cloud/network/Site2SiteCustomerGateway.java index d4facc34e75..29f580f18ba 100644 --- a/api/src/com/cloud/network/Site2SiteCustomerGateway.java +++ b/api/src/com/cloud/network/Site2SiteCustomerGateway.java @@ -9,6 +9,9 @@ public interface Site2SiteCustomerGateway extends ControlledEntity { public String getGatewayIp(); public String getGuestCidrList(); public String getIpsecPsk(); + public String getIkePolicy(); + public String getEspPolicy(); + public Long getLifetime(); public Date getRemoved(); String getName(); } 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 35394646854..61c5a7ecb02 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_guestnw.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_guestnw.sh @@ -115,7 +115,7 @@ desetup_usage() { create_guest_network() { logger -t cloud " $(basename $0): Create network on interface $dev, gateway $gw, network $ip/$mask " # setup ip configuration - sudo ip addr add dev $dev $ip/$mask + sudo ip addr add dev $dev $ip/$mask brd + sudo ip link set $dev up sudo arping -c 3 -I $dev -A -U -s $ip $ip # setup rules to allow dhcp/dns request @@ -143,7 +143,7 @@ destroy_guest_network() { 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 - destroy_acl_outbound_chain + destroy_acl_chain desetup_usage desetup_dnsmasq desetup_apache2 diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh index 40c1e4d996a..8ef19e41f45 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_ipassoc.sh @@ -58,7 +58,7 @@ add_an_ip () { sudo ip link show $ethDev | grep "state DOWN" > /dev/null local old_state=$? - sudo ip addr add dev $ethDev $pubIp/$mask + sudo ip addr add dev $ethDev $pubIp/$mask brd + if [ $old_state -eq 0 ] then sudo ip link set $ethDev up @@ -76,7 +76,7 @@ add_an_ip () { remove_an_ip () { logger -t cloud "$(basename $0):Removing ip $pubIp on interface $ethDev" - local existingIpMask=$(sudo ip addr show dev $ethDev | grep "inet " | awk '{print $2}') + local existingIpMask=$(sudo ip addr show dev $ethDev | grep -v "inet6" | grep "inet " | awk '{print $2}') sudo ip addr del dev $ethDev $pubIp/$mask # reapply IPs in this interface @@ -86,7 +86,7 @@ remove_an_ip () { then continue fi - sudo ip addr add dev $ethDev $ipMask + sudo ip addr add dev $ethDev $ipMask brd + done remove_routing @@ -148,14 +148,14 @@ fi if [ "$Aflag" == "1" ] then - add_an_ip $publicIp && + add_an_ip unlock_exit $? $lock $locked fi if [ "$Dflag" == "1" ] then - remove_an_ip $publicIp && + remove_an_ip unlock_exit $? $lock $locked fi diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_snat.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_snat.sh index ff88354dc49..3db9a2d1713 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_snat.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_snat.sh @@ -33,8 +33,6 @@ usage() { add_snat() { logger -t cloud "$(basename $0):Added SourceNAT $pubIp on interface $ethDev" vpccidr=$(getVPCcidr) - sudo iptables -D FORWARD -s $vpccidr ! -d $vpccidr -j ACCEPT - sudo iptables -A FORWARD -s $vpccidr ! -d $vpccidr -j ACCEPT sudo iptables -t nat -D POSTROUTING -j SNAT -o $ethDev --to-source $pubIp sudo iptables -t nat -A POSTROUTING -j SNAT -o $ethDev --to-source $pubIp return $? diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 175baa6dfeb..61edccbbb79 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -1588,6 +1588,7 @@ public class ApiResponseHelper implements ResponseGenerator { nicResponse.setGateway(singleNicProfile.getGateway()); nicResponse.setNetmask(singleNicProfile.getNetmask()); nicResponse.setNetworkid(singleNicProfile.getNetworkId()); + nicResponse.setNetworkName(ApiDBUtils.findNetworkById(singleNicProfile.getNetworkId()).getName() ); if (acct.getType() == Account.ACCOUNT_TYPE_ADMIN) { if (singleNicProfile.getBroadCastUri() != null) { nicResponse.setBroadcastUri(singleNicProfile.getBroadCastUri().toString()); @@ -3914,6 +3915,10 @@ public class ApiResponseHelper implements ResponseGenerator { response.setGatewayIp(result.getGatewayIp()); response.setGuestCidrList(result.getGuestCidrList()); response.setIpsecPsk(result.getIpsecPsk()); + response.setIkePolicy(result.getIkePolicy()); + response.setEspPolicy(result.getEspPolicy()); + response.setLifetime(result.getLifetime()); + response.setRemoved(result.getRemoved()); response.setObjectName("vpncustomergateway"); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 8c855af2ff2..d4fd891edd7 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2935,6 +2935,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag "service disabled are allowed in security group enabled zone", null); } } + + //don't allow eip/elb networks in Advance zone + if (ntwkOff.getElasticIp() || ntwkOff.getElasticLb()) { + throw new InvalidParameterValueException("Elastic IP and Elastic LB services are supported in zone of type " + NetworkType.Basic, null); + } } // VlanId can be specified only when network offering supports it diff --git a/server/src/com/cloud/network/Site2SiteCustomerGatewayVO.java b/server/src/com/cloud/network/Site2SiteCustomerGatewayVO.java index 5063f780b30..573d5f1445b 100644 --- a/server/src/com/cloud/network/Site2SiteCustomerGatewayVO.java +++ b/server/src/com/cloud/network/Site2SiteCustomerGatewayVO.java @@ -118,7 +118,8 @@ public class Site2SiteCustomerGatewayVO implements Site2SiteCustomerGateway { this.removed = removed; } - public long getLifetime() { + @Override + public Long getLifetime() { return lifetime; } @@ -126,6 +127,7 @@ public class Site2SiteCustomerGatewayVO implements Site2SiteCustomerGateway { this.lifetime = lifetime; } + @Override public String getIkePolicy() { return ikePolicy; } @@ -134,6 +136,7 @@ public class Site2SiteCustomerGatewayVO implements Site2SiteCustomerGateway { this.ikePolicy = ikePolicy; } + @Override public String getEspPolicy() { return espPolicy; } diff --git a/server/src/com/cloud/network/dao/Site2SiteCustomerGatewayDao.java b/server/src/com/cloud/network/dao/Site2SiteCustomerGatewayDao.java index 5b39dbdb080..78546891770 100644 --- a/server/src/com/cloud/network/dao/Site2SiteCustomerGatewayDao.java +++ b/server/src/com/cloud/network/dao/Site2SiteCustomerGatewayDao.java @@ -1,9 +1,12 @@ package com.cloud.network.dao; +import java.util.List; + import com.cloud.network.Site2SiteCustomerGatewayVO; import com.cloud.utils.db.GenericDao; public interface Site2SiteCustomerGatewayDao extends GenericDao { Site2SiteCustomerGatewayVO findByGatewayIp(String ip); Site2SiteCustomerGatewayVO findByName(String name); + List listByAccountId(long accountId); } diff --git a/server/src/com/cloud/network/dao/Site2SiteCustomerGatewayDaoImpl.java b/server/src/com/cloud/network/dao/Site2SiteCustomerGatewayDaoImpl.java index 80b5c02f512..c3a4d9446cd 100644 --- a/server/src/com/cloud/network/dao/Site2SiteCustomerGatewayDaoImpl.java +++ b/server/src/com/cloud/network/dao/Site2SiteCustomerGatewayDaoImpl.java @@ -1,5 +1,7 @@ package com.cloud.network.dao; +import java.util.List; + import javax.ejb.Local; import org.apache.log4j.Logger; @@ -19,6 +21,7 @@ public class Site2SiteCustomerGatewayDaoImpl extends GenericDaoBase listByAccountId(long accountId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("accountId", accountId); + return listBy(sc, null); + } } diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManager.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManager.java index 567b76549df..922ac2c4b6e 100644 --- a/server/src/com/cloud/network/vpn/Site2SiteVpnManager.java +++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManager.java @@ -10,4 +10,5 @@ public interface Site2SiteVpnManager extends Site2SiteVpnService { boolean cleanupVpnGatewayByVpc(long vpcId); void markDisconnectVpnConnByVpc(long vpcId); List getConnectionsForRouter(DomainRouterVO router); + boolean deleteCustomerGatewayByAccount(long accountId); } diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java index 1d2ab5d6bb4..e0d2c877fbb 100644 --- a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java @@ -269,11 +269,16 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnManager, Manager { throw new InvalidParameterValueException("Fail to find customer gateway by id", null); } _accountMgr.checkAccess(caller, null, false, customerGateway); + + return doDeleteCustomerGateway(customerGateway); + } + protected boolean doDeleteCustomerGateway(Site2SiteCustomerGateway gw) { + long id = gw.getId(); List vpnConnections = _vpnConnectionDao.listByCustomerGatewayId(id); if (vpnConnections != null && vpnConnections.size() != 0) { List idList = new ArrayList(); - idList.add(new IdentityProxy(customerGateway, id, "customerGatewayId")); + idList.add(new IdentityProxy(gw, id, "customerGatewayId")); throw new InvalidParameterValueException("Unable to delete VPN customer gateway with specified id because there is still related VPN connections!", idList); } _customerGatewayDao.remove(id); @@ -613,4 +618,14 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnManager, Manager { conns.addAll(_vpnConnectionDao.listByVpcId(vpcId)); return conns; } + + @Override + public boolean deleteCustomerGatewayByAccount(long accountId) { + boolean result = true;; + List gws = _customerGatewayDao.listByAccountId(accountId); + for (Site2SiteCustomerGatewayVO gw : gws) { + result = result & doDeleteCustomerGateway(gw); + } + return result; + } } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 063e8e004d5..7f5d5828f2e 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -70,16 +70,22 @@ import com.cloud.network.IpAddress; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.RemoteAccessVpnVO; +import com.cloud.network.Site2SiteCustomerGatewayVO; +import com.cloud.network.Site2SiteVpnConnectionVO; import com.cloud.network.VpnUserVO; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.RemoteAccessVpnDao; +import com.cloud.network.dao.Site2SiteCustomerGatewayDao; +import com.cloud.network.dao.Site2SiteVpnConnectionDao; +import com.cloud.network.dao.Site2SiteVpnGatewayDao; import com.cloud.network.dao.VpnUserDao; import com.cloud.network.security.SecurityGroupManager; import com.cloud.network.security.dao.SecurityGroupDao; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcManager; import com.cloud.network.vpn.RemoteAccessVpnService; +import com.cloud.network.vpn.Site2SiteVpnManager; import com.cloud.projects.Project; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.projects.ProjectInvitationVO; @@ -208,6 +214,8 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag private VpcManager _vpcMgr; @Inject private DomainRouterDao _routerDao; + @Inject + Site2SiteVpnManager _vpnMgr; private Adapters _userAuthenticators; @@ -560,7 +568,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag s_logger.warn("Failed to cleanup remote access vpn resources as a part of account id=" + accountId + " cleanup due to Exception: ", ex); accountCleanupNeeded = true; } - + // Cleanup security groups int numRemoved = _securityGroupDao.removeByAccountId(accountId); s_logger.info("deleteAccount: Deleted " + numRemoved + " network groups for account " + accountId); @@ -611,6 +619,12 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } } + // Delete Site 2 Site VPN customer gateway + s_logger.debug("Deleting site-to-site VPN customer gateways for account " + accountId); + if (!_vpnMgr.deleteCustomerGatewayByAccount(accountId)) { + s_logger.warn("Fail to delete site-to-site VPN customer gateways for account " + accountId); + } + // delete account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned // up successfully if (networksDeleted) { diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index 04b83398ec4..39e8d6e9293 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -550,7 +550,7 @@ label: 'Edit', action: function(args) { var array1 = []; - if(args.data.displayname != args.context.instances[0].name) + if(args.data.displayname != args.context.instances[0].displayname) array1.push("&displayName=" + args.data.displayname); array1.push("&group=" + args.data.group); @@ -1179,9 +1179,11 @@ nics: { title: 'label.nics', multiple: true, + cache:false, fields: [ { name: { label: 'label.name', header: true }, + networkname: {label: 'Network Name' }, ipaddress: { label: 'label.ip.address' }, type: { label: 'label.type' }, gateway: { label: 'label.gateway' }, @@ -1195,17 +1197,32 @@ } ], dataProvider: function(args) { - args.response.success({data: $.map(args.context.instances[0].nic, function(nic, index) { - var name = 'NIC ' + (index + 1); + + $.ajax({ + url:createURL("listVirtualMachines&details=nics&id=" + args.context.instances[0].id), + dataType: "json", + async:true, + success:function(json) { + + args.response.success({ + data: $.map(args.context.instances[0].nic, function(nic, index) { + var name = 'NIC ' + (index + 1); + var networkname = json.listvirtualmachinesresponse.virtualmachine[0].nic[index].networkname; + if (nic.isdefault) { + name += ' (' + _l('label.default') + ')'; + } + return $.extend(nic, { + name: name, + networkname: networkname + }); + }) + }); - if (nic.isdefault) { - name += ' (' + _l('label.default') + ')'; - } - return $.extend(nic, { - name: name + } }); - })}); + } + }, /** diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 494e11f964c..2e6d4296a21 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -2226,6 +2226,13 @@ } }, multipleAdd: true, + fieldPreFilter: function(args) { + var context = args.context; + var fields = args.fields; + + // Returns fields to be hidden + return []; + }, fields: { 'name': { edit: true, label: 'label.name', isEditable: true }, 'publicport': { edit: true, label: 'label.public.port' }, diff --git a/ui/scripts/ui-custom/vpc.js b/ui/scripts/ui-custom/vpc.js index c65a5b73b78..5d400bbedc3 100644 --- a/ui/scripts/ui-custom/vpc.js +++ b/ui/scripts/ui-custom/vpc.js @@ -194,6 +194,7 @@ maximizeIfSelected: true, complete: function($panel) { $panel.detailView($.extend(true, {}, detailView, { + $browser: $browser, context: context })); } diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js index 2243385e0d5..f13adb59f78 100644 --- a/ui/scripts/ui/widgets/multiEdit.js +++ b/ui/scripts/ui/widgets/multiEdit.js @@ -19,7 +19,7 @@ /** * Append item to list */ - addItem: function(data, fields, $multi, itemData, actions, options) { + addItem: function(data, fields, hiddenFields, $multi, itemData, actions, options) { if (!options) options = {}; var $tr; @@ -35,7 +35,8 @@ // Setup columns $.each(fields, function(fieldName, field) { - if (options.ignoreEmptyFields && !data[fieldName]) { + if ((options.ignoreEmptyFields && !data[fieldName]) || + $.inArray(fieldName.toString(), hiddenFields) > -1) { return true; } @@ -682,6 +683,16 @@ var context = args.context; var ignoreEmptyFields = args.ignoreEmptyFields; var actionPreFilter = args.actionPreFilter; + var fieldPreFilter = args.fieldPreFilter; + var hiddenFields = []; + + if (fieldPreFilter) { + hiddenFields = fieldPreFilter({ + fields: $.map(fields, function(v, k) { return k; }), + context: context, + $multi: $multi + }); + } var $thead = $('').appendTo( $('').appendTo($inputTable) @@ -693,6 +704,8 @@ // Setup input table headers $.each(args.fields, function(fieldName, field) { + if ($.inArray(fieldName.toString(), hiddenFields) > -1) return true; + var $th = $('').addClass(fieldName).html(_l(field.label.toString())); $th.attr('rel', fieldName); $th.appendTo($thead); @@ -929,6 +942,7 @@ _medit.addItem( data, fields, + hiddenFields, $multi, itemData, actions, diff --git a/ui/scripts/ui/widgets/tagger.js b/ui/scripts/ui/widgets/tagger.js index f671342c99c..dfc31129e95 100644 --- a/ui/scripts/ui/widgets/tagger.js +++ b/ui/scripts/ui/widgets/tagger.js @@ -1,13 +1,37 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + (function($, cloudStack) { + var isFormValid = function($form) { + var key = $form.find('input[name=key]').val(); + var value = $form.find('input[name=value]').val(); + + if (!key || !value) { + cloudStack.dialog.notice({ message: 'Please specify a tag key and value' }); + + return false; + } + + return true; + }; + var elems = { inputArea: function(args) { var $form = $('
').addClass('tag-input'); var $keyField = $('
').addClass('field key'); var $keyLabel = $('