You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ta...@apache.org on 2015/04/03 11:59:40 UTC

git commit: updated refs/heads/master to 799a033

Repository: cloudstack
Updated Branches:
  refs/heads/master 3f89cd649 -> 799a03398


CLOUDSTACK-8361: Adding functionality in marvin to check the port groups in VCenter corresponding to configuration of traffics in physical networks

Signed-off-by: SrikanteswaraRao Talluri <ta...@apache.org>
This closes #144


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/799a0339
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/799a0339
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/799a0339

Branch: refs/heads/master
Commit: 799a03398c23090818ae832108a12632a2f33ab3
Parents: 3f89cd6
Author: Gaurav Aradhye <ga...@clogeny.com>
Authored: Fri Apr 3 14:56:42 2015 +0530
Committer: SrikanteswaraRao Talluri <ta...@apache.org>
Committed: Fri Apr 3 15:28:48 2015 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/codes.py      |   9 ++
 tools/marvin/marvin/lib/base.py   |  28 ++++
 tools/marvin/marvin/lib/common.py | 260 ++++++++++++++++++++++++++++++++-
 3 files changed, 293 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/799a0339/tools/marvin/marvin/codes.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codes.py b/tools/marvin/marvin/codes.py
index 877d686..3f9ee2f 100644
--- a/tools/marvin/marvin/codes.py
+++ b/tools/marvin/marvin/codes.py
@@ -111,6 +111,7 @@ CHILD_DOMAIN_ADMIN="child domain admin"
 Network states
 '''
 ALLOCATED = "Allocated"
+
 '''
 Storage Tags
 '''
@@ -118,3 +119,11 @@ ZONETAG1 = "zwps1"
 ZONETAG2 = "zwps2"
 CLUSTERTAG1 = "cwps1"
 CLUSTERTAG2 = "cwps2"
+
+'''
+Traffic Types
+'''
+PUBLIC_TRAFFIC = "public"
+GUEST_TRAFFIC = "guest"
+MANAGEMENT_TRAFFIC = "management"
+STORAGE_TRAFFIC = "storage"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/799a0339/tools/marvin/marvin/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 91a4f60..44be8e8 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -4795,4 +4795,32 @@ class Usage:
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return(apiclient.generateUsageRecords(cmd))
 
+class TrafficType:
+    """Manage different traffic types in the setup"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists traffic types"""
+
+        cmd = listTrafficTypes.listTrafficTypesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listTrafficTypes(cmd))
+
+class StorageNetworkIpRange:
+    """Manage Storage Network Ip Range"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists Storage Network IP Ranges"""
+
+        cmd = listStorageNetworkIpRange.listStorageNetworkIpRangeCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listStorageNetworkIpRange(cmd))
+
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/799a0339/tools/marvin/marvin/lib/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/common.py b/tools/marvin/marvin/lib/common.py
index fdbf153..6efd58b 100644
--- a/tools/marvin/marvin/lib/common.py
+++ b/tools/marvin/marvin/lib/common.py
@@ -61,7 +61,8 @@ from marvin.sshClient import SshClient
 from marvin.codes import (PASS, FAILED, ISOLATED_NETWORK, VPC_NETWORK,
                           BASIC_ZONE, FAIL, NAT_RULE, STATIC_NAT_RULE,
                           RESOURCE_PRIMARY_STORAGE, RESOURCE_SECONDARY_STORAGE,
-                          RESOURCE_CPU, RESOURCE_MEMORY)
+                          RESOURCE_CPU, RESOURCE_MEMORY, PUBLIC_TRAFFIC,
+                          GUEST_TRAFFIC, MANAGEMENT_TRAFFIC, STORAGE_TRAFFIC)
 from marvin.lib.utils import (validateList, xsplit, get_process_status)
 from marvin.lib.base import (PhysicalNetwork,
                              PublicIPAddress,
@@ -80,10 +81,13 @@ from marvin.lib.base import (PhysicalNetwork,
                              Host,
                              Resources,
                              Configurations,
-                             Router)
+                             Router,
+                             PublicIpRange,
+                             StorageNetworkIpRange,
+                             TrafficType)
 import random
-
-
+import re
+import itertools
 # Import System modules
 import time
 
@@ -1417,3 +1421,251 @@ def verifyRouterState(apiclient, routerid, state, listall=True):
         exceptionMessage = e
         return [exceptionOccured, isRouterInDesiredState, exceptionMessage]
     return [exceptionOccured, isRouterInDesiredState, exceptionMessage]
+
+def analyzeTrafficType(trafficTypes, trafficTypeToFilter):
+    """ Analyze traffic types for given type and return
+        switch name and vlan Id from the
+        vmwarenetworklabel string of trafficTypeToFilter
+    """
+
+    try:
+        filteredList = [trafficType for trafficType in trafficTypes
+                        if trafficType.traffictype.lower() ==
+                        trafficTypeToFilter]
+
+        if not filteredList:
+            return [PASS, filteredList, None, None]
+
+        # Split string with , so as to extract the  switch Name and
+        # vlan ID
+        splitString = str(
+            filteredList[0].vmwarenetworklabel).split(",")
+        switchName = splitString[0]
+        vlanSpecified = splitString[1]
+
+        return [PASS, filteredList, switchName, vlanSpecified]
+    except Exception as e:
+        return [FAIL, e, None, None]
+
+
+def getExpectedPortGroupNames(
+        api_client,
+        physical_network,
+        network_rate,
+        switch_name,
+        traffic_types,
+        switch_dict,
+        vcenter_conn,
+        specified_vlan,
+        traffic_type):
+    """ Return names of expected port groups that should be
+        present in vcenter
+
+        Parameters:
+        @physical_network: Physical Network of the @traffic_type
+        @network_rate:     as defined by network.throttling.rate
+        @switch_name:      Name of the switch used by the traffic in
+                           vcenter
+        @traffic_types:    List of all traffic types present in the physical
+                           network
+        @switch_dict:      Dictionary containing switch information in vcenter
+        @vcenter_conn:     vcenter connection object used to fetch information
+                           from vcenter
+        @specified_vlan:   The vlan for @traffic_type
+        @traffic_type:     Traffic type for which the port names are to be
+                           returned
+
+        Return value:
+        [PASS/FAIL, exception object if FAIL else expected port group names
+         for @traffic_type]
+        """
+
+    try:
+        expectedDVPortGroupNames = []
+
+        if traffic_type == PUBLIC_TRAFFIC:
+            publicIpRanges = PublicIpRange.list(
+                api_client,
+                physicalnetworkid=physical_network.id
+            )
+            if publicIpRanges is not None:
+                for publicIpRange in publicIpRanges:
+                    vlanInIpRange = re.findall(
+                        '\d+',
+                        str(publicIpRange.vlan))
+                    if len(vlanInIpRange) > 0:
+                        vlanId = vlanInIpRange[0]
+                        expectedDVPortGroupName = "cloud" + "." + \
+                            PUBLIC_TRAFFIC + "." + vlanId + "." + \
+                            network_rate + "." + "1" + "-" + \
+                            switch_name
+                        expectedDVPortGroupNames.append(
+                            expectedDVPortGroupName)
+
+            expectedDVPortGroupName = "cloud" + "." + PUBLIC_TRAFFIC + "." + \
+                vlanId + "." + "0" + "." + "1" + "-" + switch_name
+            expectedDVPortGroupNames.append(expectedDVPortGroupName)
+
+        if traffic_type == GUEST_TRAFFIC:
+
+            networks = Network.list(
+                api_client,
+                physicalnetworkid=physical_network.id,
+                listall=True
+            )
+            if networks is not None:
+                for network in networks:
+                    networkVlan = re.findall(
+                        '\d+', str(network.vlan))
+                    if len(networkVlan) > 0:
+                        vlanId = networkVlan[0]
+                        expectedDVPortGroupName = "cloud" + "." + GUEST_TRAFFIC + "." + \
+                            vlanId + "." + network_rate + "." + "1" + "-" + \
+                            switch_name
+                        expectedDVPortGroupNames.append(
+                            expectedDVPortGroupName)
+
+        if traffic_type == STORAGE_TRAFFIC:
+            vlanId = ""
+            storageIpRanges = StorageNetworkIpRange.list(
+                api_client,
+                zoneid=physical_network.zoneid
+            )
+            if storageIpRanges is not None:
+                for storageIpRange in storageIpRanges:
+                    vlanInIpRange = re.findall(
+                        '\d+',
+                        str(storageIpRange.vlan))
+                    if len(vlanInIpRange) > 0:
+                        vlanId = vlanInIpRange[0]
+                    else:
+                        vlanId = "untagged"
+                    expectedDVPortGroupName = "cloud" + "." + STORAGE_TRAFFIC + \
+                        "." + vlanId + "." + "0" + "." + "1" + "-" + \
+                        switch_name
+                    expectedDVPortGroupNames.append(
+                        expectedDVPortGroupName)
+
+            else:
+                response = analyzeTrafficType(
+                    traffic_types, MANAGEMENT_TRAFFIC)
+                assert response[0] == PASS, response[1]
+                filteredList, switchName, vlanSpecified =\
+                    response[1], response[2], response[3]
+
+                if not filteredList:
+                    raise Exception("No Management traffic present and\
+                                Storage traffic does not have any IP range,\
+                                Invalid zone setting")
+
+                if switchName not in switch_dict:
+                    dvswitches = vcenter_conn.get_dvswitches(
+                        name=switchName)
+                    switch_dict[switchName] = dvswitches[0][
+                        'dvswitch']['portgroupNameList']
+
+                if vlanSpecified:
+                    vlanId = vlanSpecified
+                else:
+                    vlanId = "untagged"
+                expectedDVPortGroupName = "cloud" + "." + STORAGE_TRAFFIC + \
+                    "." + vlanId + "." + "0" + "." + "1" + "-" + switchName
+                expectedDVPortGroupNames.append(expectedDVPortGroupName)
+
+        if traffic_type == MANAGEMENT_TRAFFIC:
+            vlanId = "untagged"
+            if specified_vlan:
+                vlanId = specified_vlan
+            expectedDVPortGroupName = "cloud" + "." + "private" + "." + \
+                vlanId + "." + "0" + "." + "1" + "-" + switch_name
+            expectedDVPortGroupNames.append(expectedDVPortGroupName)
+
+    except Exception as e:
+        return [FAIL, e]
+    return [PASS, expectedDVPortGroupNames]
+
+
+def verifyVCenterPortGroups(
+        api_client,
+        vcenter_conn,
+        zone_list,
+        traffic_types_to_validate):
+
+    """ Generate expected port groups for given traffic types and
+        verify they are present in the vcenter
+
+        Parameters:
+        @api_client:    API client of root admin account
+        @vcenter_conn:  connection object for vcenter used to fetch data
+                        using vcenterAPI
+        @zone_list:     List of zones for which port groups are to be verified
+        traffic_types:  Traffic types (public, guest, management, storage) for
+                        which verification is to be done
+
+        Return value:
+        [PASS/FAIL, exception message if FAIL else None]
+    """
+    try:
+        expectedDVPortGroupNames = []
+        vcenterPortGroups = []
+        config = Configurations.list(
+            api_client,
+            name="network.throttling.rate"
+        )
+        networkRate = config[0].value
+        switchDict = {}
+        for zone in zone_list:
+            # Verify that there should be at least one physical
+            # network present in zone.
+            physicalNetworks = PhysicalNetwork.list(
+                api_client,
+                zoneid=zone.id
+            )
+            assert validateList(physicalNetworks)[0] == PASS,\
+                "listPhysicalNetworks returned invalid object in response."
+
+            for physicalNetwork in physicalNetworks:
+                trafficTypes = TrafficType.list(
+                    api_client,
+                    physicalnetworkid=physicalNetwork.id)
+
+                for trafficType in traffic_types_to_validate:
+                    response = analyzeTrafficType(
+                        trafficTypes, trafficType)
+                    assert response[0] == PASS, response[1]
+                    filteredList, switchName, vlanSpecified =\
+                        response[1], response[2], response[3]
+
+                    if not filteredList:
+                        continue
+
+                    if switchName not in switchDict:
+                        dvswitches = vcenter_conn.get_dvswitches(
+                            name=switchName)
+                        switchDict[switchName] = dvswitches[0][
+                            'dvswitch']['portgroupNameList']
+
+                    response = getExpectedPortGroupNames(
+                        api_client,
+                        physicalNetwork,
+                        networkRate,
+                        switchName,
+                        trafficTypes,
+                        switchDict,
+                        vcenter_conn,
+                        vlanSpecified,
+                        trafficType)
+                    assert response[0] == PASS, response[1]
+                    dvPortGroups = response[1]
+                    expectedDVPortGroupNames.extend(dvPortGroups)
+
+        vcenterPortGroups = list(itertools.chain(*(switchDict.values())))
+
+        for expectedDVPortGroupName in expectedDVPortGroupNames:
+            assert expectedDVPortGroupName in vcenterPortGroups,\
+                "Port group %s not present in VCenter DataCenter" %\
+                expectedDVPortGroupName
+
+    except Exception as e:
+        return [FAIL, e]
+    return [PASS, None]