New feature: Acquire specific public IP for network (#3775)

Currently in cloudstack, when we click on "Acquire New Ip", it will
randomly acquire IP from the pool. With this enhancement, it is
possible to select the IP from the drop down IP list of that network.
Same thing applies for a VPC as well.
This commit is contained in:
Rakesh 2019-12-24 10:08:53 +01:00 committed by dahn
parent 06e1212e22
commit 482e7ebf9a
10 changed files with 562 additions and 13 deletions

View File

@ -56,7 +56,7 @@ public interface NetworkService {
List<? extends Network> getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner);
IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp) throws ResourceAllocationException, InsufficientAddressCapacityException,
IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp, String ipaddress) throws ResourceAllocationException, InsufficientAddressCapacityException,
ConcurrentOperationException;
boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException;

View File

@ -125,6 +125,9 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd implements UserCmd {
authorized = {RoleType.Admin})
private Boolean display;
@Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, description="IP Address to be associated")
private String ipAddress;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -178,6 +181,10 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd implements UserCmd {
return regionId;
}
public String getIpAddress() {
return ipAddress;
}
public Long getNetworkId() {
if (vpcId != null) {
return null;
@ -306,7 +313,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd implements UserCmd {
IpAddress ip = null;
if (!isPortable()) {
ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getNetworkId(), getDisplayIp());
ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getNetworkId(), getDisplayIp(), ipAddress);
} else {
ip = _networkService.allocatePortableIP(_accountService.getAccount(getEntityOwnerId()), 1, getZoneId(), getNetworkId(), getVpcId());
}

View File

@ -169,7 +169,7 @@ public interface IpAddressManager {
PublicIp assignDedicateIpAddress(Account owner, Long guestNtwkId, Long vpcId, long dcId, boolean isSourceNat)
throws ConcurrentOperationException, InsufficientAddressCapacityException;
IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone, Boolean displayIp)
IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone, Boolean displayIp, String ipaddress)
throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException;
PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem)

View File

@ -353,7 +353,7 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro
try {
Account caller = CallContext.current().getCallingAccount();
long callerUserId = CallContext.current().getCallingUserId();
outsideIp = _ipAddrMgr.allocateIp(owner, false, caller, callerUserId, zone, true);
outsideIp = _ipAddrMgr.allocateIp(owner, false, caller, callerUserId, zone, true, null);
} catch (ResourceAllocationException e) {
s_logger.error("Unable to allocate additional public Ip address. Exception details " + e);
throw new CloudRuntimeException("Unable to allocate additional public Ip address. Exception details " + e);

View File

@ -444,7 +444,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
return allocateIp(ipOwner, isSystem, caller, callerUserId, zone, null);
return allocateIp(ipOwner, isSystem, caller, callerUserId, zone, null, null);
}
// An IP association is required in below cases
@ -1132,7 +1132,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
@DB
@Override
public IpAddress allocateIp(final Account ipOwner, final boolean isSystem, Account caller, long callerUserId, final DataCenter zone, final Boolean displayIp)
public IpAddress allocateIp(final Account ipOwner, final boolean isSystem, Account caller, long callerUserId, final DataCenter zone, final Boolean displayIp, final String ipaddress)
throws ConcurrentOperationException,
ResourceAllocationException, InsufficientAddressCapacityException {
@ -1166,7 +1166,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
ip = Transaction.execute(new TransactionCallbackWithException<PublicIp, InsufficientAddressCapacityException>() {
@Override
public PublicIp doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
PublicIp ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, null, isSystem, null, displayIp, false);
PublicIp ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, ipaddress, isSystem, null, displayIp, false);
if (ip == null) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone

View File

@ -520,7 +520,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
@Override
@ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true)
public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp)
public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp, String ipaddress)
throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException {
Account caller = CallContext.current().getCallingAccount();
@ -544,7 +544,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
}
return _ipAddrMgr.allocateIp(ipOwner, false, caller, callerUserId, zone, displayIp);
return _ipAddrMgr.allocateIp(ipOwner, false, caller, callerUserId, zone, displayIp, ipaddress);
} else {
throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone"
+ " with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled");
@ -555,7 +555,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
_accountMgr.checkAccess(caller, null, false, ipOwner);
}
return _ipAddrMgr.allocateIp(ipOwner, false, caller, callerUserId, zone, displayIp);
return _ipAddrMgr.allocateIp(ipOwner, false, caller, callerUserId, zone, displayIp, ipaddress);
}
@Override

View File

@ -160,7 +160,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
* @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, long, java.lang.Long)
*/
@Override
public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp) throws ResourceAllocationException, InsufficientAddressCapacityException,
public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp, String ipaddress) throws ResourceAllocationException, InsufficientAddressCapacityException,
ConcurrentOperationException {
// TODO Auto-generated method stub
return null;

View File

@ -0,0 +1,486 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with 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.
"""
Tests of acquiring a specified public IP for isolated network or vpc
"""
# Import Local Modules
from nose.plugins.attrib import attr
from marvin.cloudstackTestCase import cloudstackTestCase, unittest
from marvin.cloudstackAPI import createVlanIpRange
from marvin.lib.utils import (validateList,
cleanup_resources)
from marvin.lib.base import (Account,
Domain,
Configurations,
VirtualMachine,
ServiceOffering,
VpcOffering,
Zone,
Network,
VPC,
PublicIPAddress,
PublicIpRange)
from marvin.lib.common import (get_domain,
get_zone,
get_free_vlan,
get_template)
import logging
import random
class TestAcquireSpecifiedPublicIp(cloudstackTestCase):
@classmethod
def setUpClass(cls):
cls.testClient = super(
TestAcquireSpecifiedPublicIp,
cls).getClsTestClient()
cls.apiclient = cls.testClient.getApiClient()
cls.services = cls.testClient.getParsedTestDataConfig()
zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
cls.zone = Zone(zone.__dict__)
cls.template = get_template(cls.apiclient, cls.zone.id)
cls._cleanup = []
if str(cls.zone.securitygroupsenabled) == "True":
sys.exit(1)
cls.logger = logging.getLogger("TestAcquireSpecifiedPublicIp")
cls.stream_handler = logging.StreamHandler()
cls.logger.setLevel(logging.DEBUG)
cls.logger.addHandler(cls.stream_handler)
# Get Zone, Domain and templates
cls.domain = get_domain(cls.apiclient)
# Create new domain1
cls.domain1 = Domain.create(
cls.apiclient,
services=cls.services["acl"]["domain1"],
parentdomainid=cls.domain.id)
# Create account1
cls.account1 = Account.create(
cls.apiclient,
cls.services["acl"]["accountD1"],
domainid=cls.domain1.id
)
# Create domain2
cls.domain2 = Domain.create(
cls.apiclient,
services=cls.services["acl"]["domain2"],
parentdomainid=cls.domain.id)
# Create account2
cls.account2 = Account.create(
cls.apiclient,
cls.services["acl"]["accountD2"],
domainid=cls.domain2.id
)
cls.services["publiciprange"]["zoneid"] = cls.zone.id
cls.services["publiciprange"]["forvirtualnetwork"] = "true"
# Create public ip range 1
cls.services["publiciprange"]["vlan"] = get_free_vlan(
cls.apiclient,
cls.zone.id)[1]
random_subnet_number = random.randrange(10,20)
cls.services["publiciprange"]["gateway"] = "172.16." + \
str(random_subnet_number) + ".1"
cls.services["publiciprange"]["startip"] = "172.16." + \
str(random_subnet_number) + ".2"
cls.services["publiciprange"]["endip"] = "172.16." + \
str(random_subnet_number) + ".10"
cls.services["publiciprange"]["netmask"] = "255.255.255.0"
cls.public_ip_range1 = PublicIpRange.create(
cls.apiclient,
cls.services["publiciprange"]
)
PublicIpRange.dedicate(
cls.apiclient,
cls.public_ip_range1.vlan.id,
domainid=cls.account1.domainid
)
# Create public ip range 2
cls.services["publiciprange"]["vlan"] = get_free_vlan(
cls.apiclient,
cls.zone.id)[1]
cls.services["publiciprange"]["gateway"] = "172.16." + \
str(random_subnet_number + 1) + ".1"
cls.services["publiciprange"]["startip"] = "172.16." + \
str(random_subnet_number + 1) + ".2"
cls.services["publiciprange"]["endip"] = "172.16." + \
str(random_subnet_number + 1) + ".10"
cls.services["publiciprange"]["netmask"] = "255.255.255.0"
cls.public_ip_range2 = PublicIpRange.create(
cls.apiclient,
cls.services["publiciprange"]
)
PublicIpRange.dedicate(
cls.apiclient,
cls.public_ip_range2.vlan.id,
account=cls.account1.name,
domainid=cls.account1.domainid
)
# Create public ip range 3
cls.services["publiciprange"]["vlan"] = get_free_vlan(
cls.apiclient,
cls.zone.id)[1]
cls.services["publiciprange"]["gateway"] = "172.16." + \
str(random_subnet_number + 2) + ".1"
cls.services["publiciprange"]["startip"] = "172.16." + \
str(random_subnet_number + 2) + ".2"
cls.services["publiciprange"]["endip"] = "172.16." + \
str(random_subnet_number + 2) + ".10"
cls.services["publiciprange"]["netmask"] = "255.255.255.0"
cls.public_ip_range3 = PublicIpRange.create(
cls.apiclient,
cls.services["publiciprange"]
)
PublicIpRange.dedicate(
cls.apiclient,
cls.public_ip_range3.vlan.id,
domainid=cls.account2.domainid
)
# Create public ip range 4
cls.services["publiciprange"]["vlan"] = get_free_vlan(
cls.apiclient,
cls.zone.id)[1]
cls.services["publiciprange"]["gateway"] = "172.16." + \
str(random_subnet_number + 3) + ".1"
cls.services["publiciprange"]["startip"] = "172.16." + \
str(random_subnet_number + 3) + ".2"
cls.services["publiciprange"]["endip"] = "172.16." + \
str(random_subnet_number + 3) + ".10"
cls.services["publiciprange"]["netmask"] = "255.255.255.0"
cls.public_ip_range4 = PublicIpRange.create(
cls.apiclient,
cls.services["publiciprange"]
)
PublicIpRange.dedicate(
cls.apiclient,
cls.public_ip_range4.vlan.id,
account=cls.account2.name,
domainid=cls.account2.domainid
)
# Create public ip range 5
cls.services["publiciprange"]["vlan"] = get_free_vlan(
cls.apiclient,
cls.zone.id)[1]
cls.services["publiciprange"]["gateway"] = "172.16." + \
str(random_subnet_number + 4) + ".1"
cls.services["publiciprange"]["startip"] = "172.16." + \
str(random_subnet_number + 4) + ".2"
cls.services["publiciprange"]["endip"] = "172.16." + \
str(random_subnet_number + 4) + ".10"
cls.services["publiciprange"]["netmask"] = "255.255.255.0"
cls.public_ip_range5 = PublicIpRange.create(
cls.apiclient,
cls.services["publiciprange"]
)
cls._cleanup.append(cls.account1)
cls._cleanup.append(cls.domain1)
cls._cleanup.append(cls.account2)
cls._cleanup.append(cls.domain2)
cls._cleanup.append(cls.public_ip_range1)
cls._cleanup.append(cls.public_ip_range2)
cls._cleanup.append(cls.public_ip_range3)
cls._cleanup.append(cls.public_ip_range4)
cls._cleanup.append(cls.public_ip_range5)
@classmethod
def tearDownClass(cls):
try:
cleanup_resources(cls.apiclient, cls._cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
return
def setUp(cls):
cls.apiclient = cls.testClient.getApiClient()
cls.cleanup = []
return
def tearDown(cls):
try:
cleanup_resources(cls.apiclient, cls.cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
return
@attr(tags=["advanced"], required_hardware="false")
def test_01_acquire_public_ip_in_isolated_network(self):
# Validate the following
# 1. create a vm . it will create a network as well.
# 2. assign a specified IP from subnet which is dedicated to domain1, it should succeed
# 3. assign a specified IP from subnet which is dedicated to domain1/account1, it should succeed
# 4. assign a specified IP from subnet which is dedicated to domain2, it should fail
# 5. assign a specified IP from subnet which is dedicated to domain2/account2, it should fail
# 6. update account setting use.system.public.ips to false, assign a specified IP from subnet which is public, it should fail
# 7. update account setting use.system.public.ips to true, assign a specified IP from subnet which is public, it should succeed
self.service_offering = ServiceOffering.create(
self.apiclient,
self.services["service_offering"]
)
self.cleanup.append(self.service_offering)
self.virtual_machine = VirtualMachine.create(
self.apiclient,
self.services["small"],
templateid=self.template.id,
accountid=self.account1.name,
domainid=self.account1.domainid,
serviceofferingid=self.service_offering.id,
zoneid=self.zone.id
)
networks = Network.list(
self.apiclient,
account=self.account1.name,
domainid=self.account1.domainid,
listall=True
)
self.assertEqual(
isinstance(networks, list),
True,
"List networks should return a valid response for created network"
)
network = networks[0]
# Associate IP in range dedicated to domain1
ip_address_1 = self.get_free_ipaddress(self.public_ip_range1.vlan.id)
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
networkid=network.id,
ipaddress=ip_address_1
)
self.assertIsNotNone(
ipaddress,
"Failed to Associate IP Address"
)
self.cleanup.append(ipaddress)
self.assertEqual(ipaddress.ipaddress.ipaddress, ip_address_1, "Associated IP is not same as specified")
# Associate IP in range dedicated to domain1/account1
ip_address_2 = self.get_free_ipaddress(self.public_ip_range2.vlan.id)
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
networkid=network.id,
ipaddress=ip_address_2
)
self.assertIsNotNone(
ipaddress,
"Failed to Associate IP Address"
)
self.cleanup.append(ipaddress)
self.assertEqual(ipaddress.ipaddress.ipaddress, ip_address_2, "Associated IP is not same as specified")
# Associate IP in range dedicated to domain2
ip_address_3 = self.get_free_ipaddress(self.public_ip_range3.vlan.id)
with self.assertRaises(Exception):
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
networkid=network.id,
ipaddress=ip_address_3
)
# Associate IP in range dedicated to domain2/account2
ip_address_4 = self.get_free_ipaddress(self.public_ip_range4.vlan.id)
with self.assertRaises(Exception):
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
networkid=network.id,
ipaddress=ip_address_4
)
# Associate IP in public IP pool
Configurations.update(
self.apiclient,
name="use.system.public.ips",
value="false",
accountid=self.account1.id
)
ip_address_5 = self.get_free_ipaddress(self.public_ip_range5.vlan.id)
with self.assertRaises(Exception):
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
networkid=network.id,
ipaddress=ip_address_5
)
Configurations.update(
self.apiclient,
name="use.system.public.ips",
value="true",
accountid=self.account1.id
)
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
networkid=network.id,
ipaddress=ip_address_5
)
self.assertIsNotNone(
ipaddress,
"Failed to Associate IP Address"
)
self.cleanup.append(ipaddress)
self.assertEqual(ipaddress.ipaddress.ipaddress, ip_address_5, "Associated IP is not same as specified")
self.cleanup.append(self.virtual_machine)
self.cleanup.append(self.service_offering)
return
@attr(tags=["advanced"], required_hardware="false")
def test_02_acquire_public_ip_in_vpc(self):
# Validate the following
# 1. create a VPC with default offering.
# 2. assign a specified IP from subnet which is dedicated to domain1, it should succeed
# 3. assign a specified IP from subnet which is dedicated to domain1/account1, it should succeed
# 4. assign a specified IP from subnet which is dedicated to domain2, it should fail
# 5. assign a specified IP from subnet which is dedicated to domain2/account2, it should fail
# 6. update account setting use.system.public.ips to false, assign a specified IP from subnet which is public, it should fail
# 7. update account setting use.system.public.ips to true, assign a specified IP from subnet which is public, it should succeed
vpcOffering = VpcOffering.list(self.apiclient, name="Default VPC offering")
vpc = VPC.create(
apiclient=self.apiclient,
services=self.services["vpc"],
vpcofferingid=vpcOffering[0].id,
zoneid=self.zone.id,
account=self.account1.name,
domainid=self.account1.domainid
)
# Associate IP in range dedicated to domain1
ip_address_1 = self.get_free_ipaddress(self.public_ip_range1.vlan.id)
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
vpcid=vpc.id,
ipaddress=ip_address_1
)
self.assertIsNotNone(
ipaddress,
"Failed to Associate IP Address"
)
self.cleanup.append(ipaddress)
self.assertEqual(ipaddress.ipaddress.ipaddress, ip_address_1, "Associated IP is not same as specified")
# Associate IP in range dedicated to domain1/account1
ip_address_2 = self.get_free_ipaddress(self.public_ip_range2.vlan.id)
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
vpcid=vpc.id,
ipaddress=ip_address_2
)
self.assertIsNotNone(
ipaddress,
"Failed to Associate IP Address"
)
self.cleanup.append(ipaddress)
self.assertEqual(ipaddress.ipaddress.ipaddress, ip_address_2, "Associated IP is not same as specified")
# Associate IP in range dedicated to domain2
ip_address_3 = self.get_free_ipaddress(self.public_ip_range3.vlan.id)
with self.assertRaises(Exception):
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
vpcid=vpc.id,
ipaddress=ip_address_3
)
# Associate IP in range dedicated to domain2/account2
ip_address_4 = self.get_free_ipaddress(self.public_ip_range4.vlan.id)
with self.assertRaises(Exception):
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
vpcid=vpc.id,
ipaddress=ip_address_4
)
# Associate IP in public IP pool
Configurations.update(
self.apiclient,
name="use.system.public.ips",
value="false",
accountid=self.account1.id
)
ip_address_5 = self.get_free_ipaddress(self.public_ip_range5.vlan.id)
with self.assertRaises(Exception):
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
vpcid=vpc.id,
ipaddress=ip_address_5
)
Configurations.update(
self.apiclient,
name="use.system.public.ips",
value="true",
accountid=self.account1.id
)
ipaddress = PublicIPAddress.create(
self.apiclient,
zoneid=self.zone.id,
vpcid=vpc.id,
ipaddress=ip_address_5
)
self.assertIsNotNone(
ipaddress,
"Failed to Associate IP Address"
)
self.cleanup.append(ipaddress)
self.assertEqual(ipaddress.ipaddress.ipaddress, ip_address_5, "Associated IP is not same as specified")
self.cleanup.append(vpc)
return
def get_free_ipaddress(self, vlanId):
ipaddresses = PublicIPAddress.list(
self.apiclient,
vlanid=vlanId,
state='Free'
)
self.assertEqual(
isinstance(ipaddresses, list),
True,
"List ipaddresses should return a valid response for Free ipaddresses"
)
random.shuffle(ipaddresses)
return ipaddresses[0].ipaddress

View File

@ -1667,7 +1667,7 @@ class PublicIPAddress:
@classmethod
def create(cls, apiclient, accountid=None, zoneid=None, domainid=None,
services=None, networkid=None, projectid=None, vpcid=None,
isportable=False):
isportable=False, ipaddress=None):
"""Associate Public IP address"""
cmd = associateIpAddress.associateIpAddressCmd()
@ -1697,6 +1697,9 @@ class PublicIPAddress:
if vpcid:
cmd.vpcid = vpcid
if ipaddress:
cmd.ipaddress = ipaddress
return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__)
def delete(self, apiclient):
@ -4054,7 +4057,7 @@ class Configurations:
"""Manage Configuration"""
@classmethod
def update(cls, apiclient, name, value=None, zoneid=None, clusterid=None, storageid=None):
def update(cls, apiclient, name, value=None, zoneid=None, clusterid=None, storageid=None, domainid=None, accountid=None):
"""Updates the specified configuration"""
cmd = updateConfiguration.updateConfigurationCmd()
@ -4067,6 +4070,10 @@ class Configurations:
cmd.clusterid = clusterid
if storageid:
cmd.storageid = storageid
if domainid:
cmd.domainid = domainid
if accountid:
cmd.accountid = accountid
apiclient.updateConfiguration(cmd)
@classmethod

View File

@ -2121,6 +2121,50 @@
});
},
isHidden: true
},
ipaddress: {
label: 'label.ip.address',
select: function(args) {
var data = {
forvirtualnetwork : true,
allocatedonly: false
};
if ('vpc' in args.context) { //from VPC section
$.extend(data, {
zoneid: args.context.vpc[0].zoneid,
domainid: args.context.vpc[0].domainid,
account: args.context.vpc[0].account
});
} else if ('networks' in args.context) { //from Guest Network section
$.extend(data, {
zoneid: args.context.networks[0].zoneid,
domainid: args.context.networks[0].domainid,
account: args.context.networks[0].account
});
}
$.ajax({
url: createURL('listPublicIpAddresses'),
data: data,
success: function(json) {
var ips = json.listpublicipaddressesresponse.publicipaddress;
var items = [{
id: -1,
description: ''
}];
$(ips).each(function() {
if (this.state == "Free") {
items.push({
id: this.ipaddress,
description: this.ipaddress
});
}
});
args.response.success({
data: items
});
}
})
}
}
}
},
@ -2149,6 +2193,11 @@
}
}
if (args.data.ipaddress != null && args.data.ipaddress.length > 0) {
$.extend(dataObj, {
ipaddress: args.data.ipaddress
});
}
$.ajax({
url: createURL('associateIpAddress'),
data: dataObj,