This commit is contained in:
Sateesh Chodapuneedi 2013-06-06 14:34:50 +05:30
commit 89fa121a0c
28 changed files with 679 additions and 137 deletions

View File

@ -0,0 +1,22 @@
<!-- 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.
-->
<!ENTITY PRODUCT "CloudStack">
<!ENTITY BOOKID "Technical Documentation">
<!ENTITY YEAR "2013">
<!ENTITY HOLDER "Apache Software Foundation">

View File

@ -0,0 +1,52 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "CloudStack_GSoC_Guide.ent">
%BOOK_ENTITIES;
<!ENTITY % xinclude SYSTEM "http://www.docbook.org/xml/4.4/xinclude.mod">
%xinclude;
]>
<!-- 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.
-->
<book>
<bookinfo id="cloudstack_gsoc_2013">
<title>&PRODUCT; Guide for the 2013 Google Summer of Code</title>
<productname>Apache CloudStack</productname>
<productnumber>4.3.0</productnumber>
<edition>1</edition>
<pubsnumber></pubsnumber>
<abstract>
<para>
Guide for 2013 Google Summer of Code Projects.
</para>
</abstract>
<corpauthor>
<inlinemediaobject>
<imageobject>
<imagedata fileref="Common_Content/images/title_logo.svg" format="SVG" />
</imageobject>
</inlinemediaobject>
</corpauthor>
<xi:include href="Common_Content/Legal_Notice.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</bookinfo>
<xi:include href="gsoc-tuna.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</book>

28
docs/en-US/gsoc-tuna.xml Normal file
View File

@ -0,0 +1,28 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "CloudStack_GSoC_Guide.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="gsoc-tuna">
<title>Nguyen's 2013 GSoC Proposal</title>
<para>This chapter describes Nguyen 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.</para>
</chapter>

View File

@ -27,7 +27,8 @@
Basic zones and security groups-enabled Advanced zones. For security groups-enabled Advanced
zones, it implies multiple subnets can be added to the same VLAN. With the addition of this
feature, you will be able to add IP address ranges from the same subnet or from a different one
when IP address are exhausted. To support this feature, the capability of
when IP address are exhausted. This would in turn allows you to employ higher number of subnets
and thus reduce the address management overhead. To support this feature, the capability of
<code>createVlanIpRange</code> API is extended to add IP ranges also from a different
subnet.</para>
<para>Ensure that you manually configure the gateway of the new subnet before adding the IP range.

57
docs/en-US/pvlan.xml Normal file
View File

@ -0,0 +1,57 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<section id="pvlan">
<title>Isolation in Advanced Zone Using Private VLAN</title>
<para/>
<section id="about-pvlan">
<title>About Private VLAN</title>
<para>In an Ethernet switch, a VLAN is a broadcast domain in which hosts can establish direct
communication with each another at Layer 2. Private VLAN is designed as an extension of VLAN
standard to add further segmentation of the logical broadcast domain. A regular VLAN is a
single broadcast domain, whereas a private VLAN partitions a larger VLAN broadcast domain into
smaller sub-domains. A sub-domain is represented by a pair of VLANs: a Primary VLAN and a
Secondary VLAN. The original VLAN that is being divided into smaller groups is called
Primary, That implies all VLAN pairs in a private VLAN share the same Primary VLAN. All the
secondary VLANs exist only inside the Primary. Each Secondary VLAN has a specific VLAN ID
associated to it, which differentiates one sub-domain from another.</para>
<para>For further reading:</para>
<itemizedlist>
<listitem>
<para><ulink
url="http://www.cisco.com/en/US/docs/switches/lan/catalyst3750/software/release/12.2_25_see/configuration/guide/swpvlan.html#wp1038379"
>Understanding Private VLANs</ulink></para>
</listitem>
<listitem>
<para><ulink url="http://tools.ietf.org/html/rfc5517">Cisco Systems' Private VLANs: Scalable
Security in a Multi-Client Environment</ulink></para>
</listitem>
<listitem>
<para><ulink url="http://kb.vmware.com">Private VLAN (PVLAN) on vNetwork Distributed Switch
- Concept Overview (1010691)</ulink></para>
</listitem>
</itemizedlist>
</section>
<section id="prereq-pvlan">
<title>Prerequisites</title>
<para>Ensure that you configure private VLAN on your physical switches out-of-band.</para>
</section>
</section>

View File

@ -0,0 +1,27 @@
# Publican configuration file for CloudStack Complete Documentation Set
# Contains all technical docs except release notes
# Config::Simple 4.58
# Tue May 29 00:57:27 2012
#
# 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.
xml_lang: en-US
type: Book
docname: CloudStack_GSoC_Guide
brand: cloudstack
chunk_first: 1
chunk_section_depth: 1

View File

@ -54,10 +54,9 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long> {
/**
* List user vm instances with virtualized networking (i.e. not direct attached networking) for the given account and datacenter
* @param accountId will search for vm instances belonging to this account
* @param dcId will search for vm instances in this zone
* @return the list of vm instances owned by the account in the given data center that have virtualized networking (not direct attached networking)
*/
List<UserVmVO> listVirtualNetworkInstancesByAcctAndZone(long accountId, long dcId, long networkId);
List<UserVmVO> listVirtualNetworkInstancesByAcctAndNetwork(long accountId, long networkId);
List<UserVmVO> listByNetworkIdAndStates(long networkId, State... states);

View File

@ -283,11 +283,10 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
}
@Override
public List<UserVmVO> listVirtualNetworkInstancesByAcctAndZone(long accountId, long dcId, long networkId) {
public List<UserVmVO> listVirtualNetworkInstancesByAcctAndNetwork(long accountId, long networkId) {
SearchCriteria<UserVmVO> sc = AccountDataCenterVirtualSearch.create();
sc.setParameters("account", accountId);
sc.setParameters("dc", dcId);
sc.setJoinParameters("nicSearch", "networkId", networkId);
return listBy(sc);

View File

@ -1835,9 +1835,8 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
}
}
IPAddressVO addr = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId());
List<UserVmVO> userVms = _vmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(),
addr.getDataCenterId(), loadBalancer.getNetworkId());
List<UserVmVO> userVms = _vmDao.listVirtualNetworkInstancesByAcctAndNetwork(loadBalancer.getAccountId(),
loadBalancer.getNetworkId());
for (UserVmVO userVm : userVms) {
// if the VM is destroyed, being expunged, in an error state, or in

View File

@ -4709,7 +4709,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Override
public void prepareStop(VirtualMachineProfile<UserVmVO> profile) {
UserVmVO vm = profile.getVirtualMachine();
UserVmVO vm = _vmDao.findById(profile.getId());
if (vm.getState() == State.Running)
collectVmDiskStatistics(vm);
}

View File

@ -170,10 +170,10 @@ class TestInternalLb(cloudstackTestCase):
networkid=ntwk.id)
#5) Assign the VM to the Internal Load Balancer
applb.assign(self.apiclient, vms=[vm.id])
applb.assign(self.apiclient, vms=[vm])
#6) Remove the vm from the Interanl Load Balancer
applb.remove(self.apiclient, vms=[vm.id])
applb.remove(self.apiclient, vms=[vm])
#7) Delete the Load Balancer
applb.delete(self.apiclient)

View File

@ -485,7 +485,7 @@ class TestISO(cloudstackTestCase):
if len(self.zones) <= 1:
self.skipTest("Not enough zones available to perform copy template")
self.services["destzoneid"] = filter(lambda z: z.id != self.zone.id, self.zones)[0]
self.services["destzoneid"] = filter(lambda z: z.id != self.zone.id, self.zones)[0].id
self.debug("Copy ISO from %s to %s" % (
self.zone.id,

View File

@ -24,96 +24,154 @@ from marvin.integration.lib.base import *
from marvin.integration.lib.common import *
from nose.plugins.attrib import attr
class Services:
def __init__(self):
self.services = {
"account": {
"email": "test@test.com",
"firstname": "Test",
"lastname": "User",
"username": "test",
"password": "password",
},
"virtual_machine": {
"displayname": "Test VM",
"username": "root",
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"ostype": 'CentOS 5.3 (64-bit)',
"service_offering": {
"name": "Tiny Instance",
"displaytext": "Tiny Instance",
"cpunumber": 1,
"cpuspeed": 100,
"memory": 256,
},
"network_offering": {
"name": "Network offering for internal lb service",
"displaytext": "Network offering for internal lb service",
"guestiptype": "Isolated",
"traffictype": "Guest",
"supportedservices": "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL",
"serviceProviderList": {
"Dhcp": "VpcVirtualRouter",
"Dns": "VpcVirtualRouter",
"Vpn": "VpcVirtualRouter",
"UserData": "VpcVirtualRouter",
"Lb": "InternalLbVM",
"SourceNat": "VpcVirtualRouter",
"StaticNat": "VpcVirtualRouter",
"PortForwarding": "VpcVirtualRouter",
"NetworkACL": "VpcVirtualRouter",
},
"serviceCapabilityList": {
"SourceNat": {"SupportedSourceNatTypes": "peraccount"},
"Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"}
}
}
}
class TestNetworkACL(cloudstackTestCase):
networkOfferingId = 11
networkId = None
vmId = None
vpcId = None
aclId = None
zoneId = 1
serviceOfferingId = 1
templateId = 5
@classmethod
def setUpClass(cls):
cls.apiclient = super(TestNetworkACL, cls).getClsTestClient().getApiClient()
cls.services = Services().services
cls.zone = get_zone(cls.apiclient, cls.services)
cls.domain = get_domain(cls.apiclient)
cls.service_offering = ServiceOffering.create(
cls.apiclient,
cls.services["service_offering"]
)
cls.account = Account.create(cls.apiclient, services=cls.services["account"])
cls.template = get_template(
cls.apiclient,
cls.zone.id,
cls.services["ostype"]
)
cls.debug("Successfully created account: %s, id: \
%s" % (cls.account.name,\
cls.account.id))
cls.cleanup = [cls.account]
def setUp(self):
self.apiClient = self.testClient.getApiClient()
@attr(tags=["advanced"])
def test_networkAcl(self):
def test_network_acl(self):
"""Test network ACL lists and items in VPC"""
# 0) Get the default network offering for VPC
networkOffering = NetworkOffering.list(self.apiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks")
self.assert_(networkOffering is not None and len(networkOffering) > 0, "No VPC based network offering")
# 1) Create VPC
self.createVPC()
vpcOffering = VpcOffering.list(self.apiclient)
self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found")
self.services["vpc"] = {}
self.services["vpc"]["name"] = "vpc-networkacl"
self.services["vpc"]["displaytext"] = "vpc-networkacl"
self.services["vpc"]["cidr"] = "10.1.1.0/24"
vpc = VPC.create(
apiclient=self.apiclient,
services=self.services["vpc"],
networkDomain="vpc.networkacl",
vpcofferingid=vpcOffering[0].id,
zoneid=self.zone.id,
account=self.account.name,
domainid=self.domain.id
)
self.assert_(vpc is not None, "VPC creation failed")
# 2) Create ACl
self.createACL()
# 2) Create ACL
aclgroup = NetworkACLList.create(apiclient=self.apiclient, services={}, name="acl", description="acl", vpcid=vpc.id)
self.assertIsNotNone(aclgroup, "Failed to create NetworkACL list")
self.debug("Created a network ACL list %s" % aclgroup.name)
# 3) Create ACl Item
self.createACLItem()
# 3) Create ACL Item
aclitem = NetworkACL.create(apiclient=self.apiclient, services={},
protocol="TCP", number="10", action="Deny", aclid=aclgroup.id, cidrlist=["0.0.0.0/0"])
self.assertIsNotNone(aclitem, "Network failed to aclItem")
self.debug("Added a network ACL %s to ACL list %s" % (aclitem.id, aclgroup.name))
# 4) Create network with ACL
self.createNetwork()
self.services["vpcnetwork"] = {}
self.services["vpcnetwork"]["name"] = "vpcntwk"
self.services["vpcnetwork"]["displaytext"] = "vpcntwk"
ntwk = Network.create(
apiclient=self.apiclient,
services=self.services["vpcnetwork"],
accountid=self.account.name,
domainid=self.domain.id,
networkofferingid=networkOffering[0].id,
zoneid=self.zone.id,
vpcid=vpc.id,
aclid=aclgroup.id,
gateway="10.1.1.1",
netmask="255.255.255.192"
)
self.assertIsNotNone(ntwk, "Network failed to create")
self.debug("Network %s created in VPC %s" %(ntwk.id, vpc.id))
# 5) Deploy a vm
self.deployVm()
self.services["virtual_machine"]["networkids"] = ntwk.id
vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
templateid=self.template.id,
zoneid=self.zone.id,
accountid=self.account.name,
domainid= self.domain.id,
serviceofferingid=self.service_offering.id,
)
self.assert_(vm is not None, "VM failed to deploy")
self.assert_(vm.state == 'Running', "VM is not running")
self.debug("VM %s deployed in VPC %s" %(vm.id, vpc.id))
def createACL(self):
createAclCmd = createNetworkACLList.createNetworkACLListCmd()
createAclCmd.name = "acl1"
createAclCmd.description = "new acl"
createAclCmd.vpcId = TestNetworkACL.vpcId
createAclResponse = self.apiClient.createNetworkACLList(createAclCmd)
TestNetworkACL.aclId = createAclResponse.id
def createACLItem(self):
createAclItemCmd = createNetworkACL.createNetworkACLCmd()
createAclItemCmd.cidr = "0.0.0.0/0"
createAclItemCmd.protocol = "TCP"
createAclItemCmd.number = "10"
createAclItemCmd.action = "Deny"
createAclItemCmd.aclId = TestNetworkACL.aclId
createAclItemResponse = self.apiClient.createNetworkACL(createAclItemCmd)
self.assertIsNotNone(createAclItemResponse.id, "Network failed to aclItem")
def createVPC(self):
createVPCCmd = createVPC.createVPCCmd()
createVPCCmd.name = "new vpc"
createVPCCmd.cidr = "10.1.1.0/24"
createVPCCmd.displaytext = "new vpc"
createVPCCmd.vpcofferingid = 1
createVPCCmd.zoneid = self.zoneId
createVPCResponse = self.apiClient.createVPC(createVPCCmd)
TestNetworkACL.vpcId = createVPCResponse.id
def createNetwork(self):
createNetworkCmd = createNetwork.createNetworkCmd()
createNetworkCmd.name = "vpc network"
createNetworkCmd.displaytext = "vpc network"
createNetworkCmd.netmask = "255.255.255.0"
createNetworkCmd.gateway = "10.1.1.1"
createNetworkCmd.zoneid = self.zoneId
createNetworkCmd.vpcid = TestNetworkACL.vpcId
createNetworkCmd.networkofferingid = TestNetworkACL.networkOfferingId
createNetworkCmd.aclId = TestNetworkACL.aclId
createNetworkResponse = self.apiClient.createNetwork(createNetworkCmd)
TestNetworkACL.networkId = createNetworkResponse.id
self.assertIsNotNone(createNetworkResponse.id, "Network failed to create")
def deployVm(self):
deployVirtualMachineCmd = deployVirtualMachine.deployVirtualMachineCmd()
deployVirtualMachineCmd.networkids = TestNetworkACL.networkId
deployVirtualMachineCmd.serviceofferingid = TestNetworkACL.serviceOfferingId
deployVirtualMachineCmd.zoneid = TestNetworkACL.zoneId
deployVirtualMachineCmd.templateid = TestNetworkACL.templateId
deployVirtualMachineCmd.hypervisor = "XenServer"
deployVMResponse = self.apiClient.deployVirtualMachine(deployVirtualMachineCmd)
TestNetworkACL.vmId = deployVMResponse.id
def tearDown(self):
#destroy the vm
if TestNetworkACL.vmId is not None:
destroyVirtualMachineCmd = destroyVirtualMachine.destroyVirtualMachineCmd()
destroyVirtualMachineCmd.id = TestNetworkACL.vmId
destroyVirtualMachineResponse = self.apiClient.destroyVirtualMachine(destroyVirtualMachineCmd)
@classmethod
def tearDownClass(cls):
try:
cleanup_resources(cls.apiclient, cls.cleanup)
except Exception, e:
raise Exception("Cleanup failed with %s" % e)

View File

@ -34,6 +34,15 @@ class Services:
def __init__(self):
self.services = {
"account": {
"email": "test@test.com",
"firstname": "Test",
"lastname": "User",
"username": "test",
# Random characters are appended in create account to
# ensure unique username generated each time
"password": "password",
},
"off":
{
"name": "Service Offering",

View File

@ -665,7 +665,7 @@ class TestTemplates(cloudstackTestCase):
if len(self.zones) <= 1:
self.skipTest("Not enough zones available to perform copy template")
self.services["destzoneid"] = filter(lambda z: z.id != self.services["sourcezoneid"], self.zones)[0]
self.services["destzoneid"] = filter(lambda z: z.id != self.services["sourcezoneid"], self.zones)[0].id
self.debug("Copy template from Zone: %s to %s" % (
self.services["sourcezoneid"],

View File

@ -113,7 +113,7 @@ fix_nameserver() {
# Replace /etc/resolv.conf also
cat > /etc/resolv.conf << EOF
nameserver 8.8.8.8
nameserver 4.4.4.4
nameserver 8.8.4.4
EOF
}

View File

@ -112,7 +112,7 @@ fix_nameserver() {
# Replace /etc/resolv.conf also
cat > /etc/resolv.conf << EOF
nameserver 8.8.8.8
nameserver 4.4.4.4
nameserver 8.8.4.4
EOF
}

View File

@ -46,7 +46,7 @@
]
}
],
"dns2": "4.4.4.4",
"dns2": "8.8.4.4",
"dns1": "8.8.8.8",
"securitygroupenabled": "true",
"localstorageenabled": "true",

View File

@ -45,7 +45,7 @@
]
}
],
"dns2": "4.4.4.4",
"dns2": "8.8.4.4",
"dns1": "8.8.8.8",
"securitygroupenabled": "true",
"localstorageenabled": "true",

View File

@ -44,7 +44,7 @@
]
}
],
"dns2": "4.4.4.4",
"dns2": "8.8.4.4",
"dns1": "8.8.8.8",
"securitygroupenabled": "true",
"localstorageenabled": "true",

View File

@ -49,7 +49,7 @@
]
}
],
"dns2": "4.4.4.4",
"dns2": "8.8.4.4",
"dns1": "8.8.8.8",
"securitygroupenabled": "true",
"localstorageenabled": "true",

View File

@ -269,7 +269,7 @@ def describe_setup_in_basic_mode():
for l in range(1):
z = zone()
z.dns1 = "8.8.8.8"
z.dns2 = "4.4.4.4"
z.dns2 = "8.8.4.4"
z.internaldns1 = "192.168.110.254"
z.internaldns2 = "192.168.110.253"
z.name = "test"+str(l)
@ -390,7 +390,7 @@ def describe_setup_in_eip_mode():
for l in range(1):
z = zone()
z.dns1 = "8.8.8.8"
z.dns2 = "4.4.4.4"
z.dns2 = "8.8.4.4"
z.internaldns1 = "192.168.110.254"
z.internaldns2 = "192.168.110.253"
z.name = "test"+str(l)
@ -519,7 +519,7 @@ def describe_setup_in_advanced_mode():
for l in range(1):
z = zone()
z.dns1 = "8.8.8.8"
z.dns2 = "4.4.4.4"
z.dns2 = "8.8.4.4"
z.internaldns1 = "192.168.110.254"
z.internaldns2 = "192.168.110.253"
z.name = "test"+str(l)
@ -645,7 +645,7 @@ def describe_setup_in_advancedsg_mode():
for l in range(1):
z = zone()
z.dns1 = "8.8.8.8"
z.dns2 = "4.4.4.4"
z.dns2 = "8.8.4.4"
z.internaldns1 = "192.168.110.254"
z.internaldns2 = "192.168.110.253"
z.name = "test"+str(l)

View File

@ -1800,7 +1800,7 @@ class Network:
def create(cls, apiclient, services, accountid=None, domainid=None,
networkofferingid=None, projectid=None,
subdomainaccess=None, zoneid=None,
gateway=None, netmask=None, vpcid=None, guestcidr=None):
gateway=None, netmask=None, vpcid=None, aclid=None, guestcidr=None):
"""Create Network for account"""
cmd = createNetwork.createNetworkCmd()
cmd.name = services["name"]
@ -1846,6 +1846,8 @@ class Network:
cmd.guestcidr = guestcidr
if vpcid:
cmd.vpcid = vpcid
if aclid:
cmd.aclid = aclid
return Network(apiclient.createNetwork(cmd).__dict__)
def delete(self, apiclient):
@ -1888,25 +1890,55 @@ class NetworkACL:
self.__dict__.update(items)
@classmethod
def create(cls, apiclient, networkid, services, traffictype=None):
def create(cls, apiclient, services, networkid=None, protocol=None,
number=None, aclid=None, action='Allow', traffictype=None, cidrlist=[]):
"""Create network ACL rules(Ingress/Egress)"""
cmd = createNetworkACL.createNetworkACLCmd()
cmd.networkid = networkid
if "networkid" in services:
cmd.networkid = services["networkid"]
elif networkid:
cmd.networkid = networkid
if "protocol" in services:
cmd.protocol = services["protocol"]
if services["protocol"] == 'ICMP':
cmd.icmptype = -1
cmd.icmpcode = -1
elif protocol:
cmd.protocol = protocol
if services["protocol"] == 'ICMP':
cmd.icmptype = -1
cmd.icmpcode = -1
else:
if "startport" in services:
cmd.startport = services["startport"]
if "endport" in services:
cmd.endport = services["endport"]
cmd.cidrlist = services["cidrlist"]
if traffictype:
if "cidrlist" in services:
cmd.cidrlist = services["cidrlist"]
elif cidrlist:
cmd.cidrlist = cidrlist
if "traffictype" in services:
cmd.traffictype = services["traffictype"]
elif traffictype:
cmd.traffictype = traffictype
# Defaulted to Ingress
if "action" in services:
cmd.action = services["action"]
elif action:
cmd.action = action
if "number" in services:
cmd.number = services["number"]
elif number:
cmd.number = number
if "aclid" in services:
cmd.aclid = services["aclid"]
elif aclid:
cmd.aclid = aclid
# Defaulted to Ingress
return NetworkACL(apiclient.createNetworkACL(cmd).__dict__)
def delete(self, apiclient):
@ -1925,6 +1957,50 @@ class NetworkACL:
return(apiclient.listNetworkACLs(cmd))
class NetworkACLList:
"""Manage Network ACL lists lifecycle"""
def __init__(self, items):
self.__dict__.update(items)
@classmethod
def create(cls, apiclient, services, name=None, description=None, vpcid=None):
"""Create network ACL container list"""
cmd = createNetworkACLList.createNetworkACLListCmd()
if "name" in services:
cmd.name = services["name"]
elif name:
cmd.name = name
if "description" in services:
cmd.description = services["description"]
elif description:
cmd.description = description
if "vpcid" in services:
cmd.vpcid = services["vpcid"]
elif vpcid:
cmd.vpcid = vpcid
return NetworkACLList(apiclient.createNetworkACLList(cmd).__dict__)
def delete(self, apiclient):
"""Delete network acl list"""
cmd = deleteNetworkACLList.deleteNetworkACLListCmd()
cmd.id = self.id
return apiclient.deleteNetworkACLList(cmd)
@classmethod
def list(cls, apiclient, **kwargs):
"""List Network ACL lists"""
cmd = listNetworkACLLists.listNetworkACLListsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listNetworkACLLists(cmd))
class Vpn:
"""Manage VPN life cycle"""

View File

@ -142,7 +142,7 @@ if __name__ == "__main__":
nsp = getResultObj(result)
print nsp[0].id
result = '{ "listzonesresponse" : { "count":1 ,"zone" : [ {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"4.4.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"5e818a11-6b00-3429-9a07-e27511d3169a","dhcpprovider":"DhcpServer"} ] } }'
result = '{ "listzonesresponse" : { "count":1 ,"zone" : [ {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"8.8.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"5e818a11-6b00-3429-9a07-e27511d3169a","dhcpprovider":"DhcpServer"} ] } }'
zones = getResultObj(result)
print zones[0].id
res = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressResponse()
@ -165,7 +165,7 @@ if __name__ == "__main__":
asynJob = getResultObj(result)
print asynJob
result = '{ "createzoneresponse" : { "zone" : {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"4.4.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"3442f287-e932-3111-960b-514d1f9c4610","dhcpprovider":"DhcpServer"} } }'
result = '{ "createzoneresponse" : { "zone" : {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"8.8.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"3442f287-e932-3111-960b-514d1f9c4610","dhcpprovider":"DhcpServer"} } }'
res = createZone.createZoneResponse()
zone = getResultObj(result, res)
print zone.id

View File

@ -154,6 +154,15 @@
cursor: pointer;
}
.vpc-network-chart .tier-item .content .dashboard-item.disabled {
/*+opacity:50%;*/
filter: alpha(opacity=50);
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
-moz-opacity: 0.5;
opacity: 0.5;
cursor: not-allowed;
}
.vpc-network-chart .tier-item .content .dashboard-item:hover {
background-color: #DBEDFE;
/*+box-shadow:inset 0px 1px 2px #000000;*/
@ -271,6 +280,8 @@
float: left;
/*+placement:shift 10px 176px;*/
position: relative;
left: 10px;
top: 176px;
left: 0px;
top: 237px;
}

View File

@ -231,7 +231,15 @@
$dashboardItem.append($total, $name);
$dashboardItem.appendTo($dashboard);
if (dashboardItem._disabled) {
$dashboardItem.addClass('disabled');
}
$dashboardItem.click(function() {
if ($dashboardItem.is('.disabled')) {
return false;
}
var section = cloudStack.vpc.sections[id];
var $section = $('<div>');
var $loading = $('<div>').addClass('loading-overlay');

View File

@ -25,6 +25,7 @@
var messages = args.action ? args.action.messages : {};
var preAction = args.action ? args.action.preAction : {};
var action = args.action ? args.action.action : {};
var needsRefresh = args.action.needsRefresh;
var section;
var data = {
id: $instanceRow.data('list-view-item-id'),
@ -142,6 +143,12 @@
$item: $instanceRow
});
} else {
if (needsRefresh) {
var $loading = $('<div>').addClass('loading-overlay');
$listView.prepend($loading);
}
var actionArgs = {
data: data,
ref: options.ref,
@ -206,6 +213,15 @@
$instanceRow.data('json-obj'),
actionFilter);
}
if (needsRefresh) {
if ($listView.closest('.detail-view').size()) {
$('.detail-view:last .button.refresh').click();
} else {
$loading.remove();
$listView.listView('refresh');
}
}
}
if (additional && additional.complete)
@ -293,7 +309,8 @@
if (!args.action.action.externalLink &&
!args.action.createForm &&
args.action.addRow != 'true' &&
!action.custom && !action.uiCustom) {
!action.custom && !action.uiCustom &&
!args.action.listView) {
cloudStack.dialog.confirm({
message: messages.confirm(messageArgs),
action: function() {
@ -306,6 +323,14 @@
});
} else if (action.custom || action.uiCustom) {
performAction();
} else if (args.action.listView) {
cloudStack.dialog.listView({
context: context,
listView: args.action.listView,
after: function(args) {
performAction(null, { context: args.context });
}
});
} else {
var addRow = args.action.addRow == "false" ? false : true;
var isHeader = args.action.isHeader;

View File

@ -57,6 +57,13 @@
}
},
fields: {
'rulenumber':{
label:'Rule Number',
edit:true
},
'cidrlist': { edit: true, label: 'label.cidr' },
action: {
label: 'Action',
@ -442,8 +449,10 @@
},
detailView: {
isMaximized: true,
name: 'Internal LB details',
actions: {
/*
assignVm: {
label: 'Assign VMs to Internal LB',
messages: {
@ -507,7 +516,8 @@
notification: {
poll: pollAsyncJobResult
}
},
},
*/
remove: {
label: 'Delete Internal LB',
messages: {
@ -604,25 +614,161 @@
assignedVms: {
title: 'Assigned VMs',
multiple: true,
fields: [
{
listView: {
id: 'assignedVms',
fields: {
name: { label: 'label.name' },
ipaddress: { label: 'label.ip.address' }
}
],
dataProvider: function(args) {
$.ajax({
url: createURL('listLoadBalancers'),
data: {
id: args.context.internalLoadBalancers[0].id
},
success: function(json) {
var item = json.listloadbalancerssresponse.loadbalancer[0];
args.response.success({ data: item.loadbalancerinstance });
},
dataProvider: function(args) {
$.ajax({
url: createURL('listLoadBalancers'),
data: {
id: args.context.internalLoadBalancers[0].id
},
success: function(json) {
var item = json.listloadbalancerssresponse.loadbalancer[0];
args.response.success({ data: item.loadbalancerinstance });
}
});
},
actions: {
add: {
label: 'Assign VMs',
messages: {
notification: function(args) { return 'Assign VMs'; }
},
needsRefresh: true,
listView: $.extend(true, {}, cloudStack.sections.instances.listView, {
type: 'checkbox',
filters: false,
dataProvider: function(args) {
$.ajax({
url: createURL('listVirtualMachines'),
data: {
networkid: args.context.networks[0].id,
listAll: true
},
success: function(json) {
var instances = json.listvirtualmachinesresponse.virtualmachine;
// Pre-select existing instances in LB rule
$(instances).map(function(index, instance) {
instance._isSelected = $.grep(
args.context.internalLoadBalancers[0].loadbalancerinstance,
function(lbInstance) {
return lbInstance.id == instance.id;
}
).length ? true : false;
});
//remove assigned VMs (i.e. instance._isSelected == true)
var items = [];
if(instances != null) {
for(var i = 0; i < instances.length; i++) {
if(instances[i]._isSelected = true)
continue;
else
items.push(instances[i]);
}
}
args.response.success({
data: items
});
}
});
}
}),
action: function(args) {
var vms = args.context.instances;
var array1 = [];
for(var i = 0; i < vms.length; i++) {
array1.push(vms[i].id);
}
var virtualmachineids = array1.join(',');
$.ajax({
url: createURL('assignToLoadBalancerRule'),
data: {
id: args.context.internalLoadBalancers[0].id,
virtualmachineids: virtualmachineids
},
dataType: 'json',
async: true,
success: function(data) {
var jid = data.assigntoloadbalancerruleresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function(json) {
$('.list-view').listView('refresh');
//return json.queryasyncjobresultresponse.jobresult.volume;
}
}
});
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
});
}
},
detailView: {
actions: {
remove: {
label: 'remove VM from load balancer',
addRow: 'false',
messages: {
confirm: function(args) {
return 'Please confirm you want to remove VM from load balancer';
},
notification: function(args) {
return 'remove VM from load balancer';
}
},
action: function(args) {
$.ajax({
url: createURL('removeFromLoadBalancerRule'),
data: {
id: args.context.internalLoadBalancers[0].id,
virtualmachineids: args.context.assignedVms[0].id
},
success: function(json) {
var jid = json.removefromloadbalancerruleresponse.jobid;
args.response.success({
_custom: { jobId: jid }
});
}
});
},
notificaton: {
poll: pollAsyncJobResult
}
}
},
tabs: {
details: {
title: 'label.details',
fields: [
{
name: { label: 'label.name' }
},
{
ipaddress: { label: 'label.ip.address' }
}
],
dataProvider: function(args) {
setTimeout(function() {
args.response.success({ data: args.context.assignedVms[0] });
});
}
}
}
}
}
}
}
}
@ -3177,7 +3323,8 @@
});
}
}
}
}
},
action: function(args) {
var dataObj = {
@ -3447,17 +3594,41 @@
}
).length ? tier._highlighted = true : tier._highlighted = false;
// Get LB capabilities
var lbSchemes = $.grep(
$.grep(
tier.service,
function(service) {
return service.name == 'Lb';
}
)[0].capability,
function(capability) {
return capability.name == 'LbSchemes';
}
);
var hasLbScheme = function(schemeVal) {
return $.grep(
lbSchemes,
function(scheme) {
return scheme.value == schemeVal;
}
).length ? true : false;
};
return $.extend(tier, {
_dashboardItems: [
{
id: 'internalLoadBalancers',
name: 'Internal LB',
total: internalLoadBalancers.count
total: internalLoadBalancers.count,
_disabled: !hasLbScheme('Internal')
},
{
id: 'publicLbIps',
name: 'Public LB IP',
total: publicLbIps.count
total: publicLbIps.count,
_disabled: !hasLbScheme('Public')
},
{
id: 'tierStaticNATs',