cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tall...@apache.org
Subject [02/18] Marvin + test changes from master Signed-off-by: SrikanteswaraRao Talluri <talluri@apache.org>
Date Mon, 28 Apr 2014 11:00:03 GMT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/404ac549/tools/marvin/marvin/lib/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/common.py b/tools/marvin/marvin/lib/common.py
new file mode 100644
index 0000000..8868d2d
--- /dev/null
+++ b/tools/marvin/marvin/lib/common.py
@@ -0,0 +1,1062 @@
+# 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.
+"""Common functions
+"""
+
+# Import Local Modules
+from marvin.cloudstackAPI import (listConfigurations,
+                                  listPhysicalNetworks,
+                                  listRegions,
+                                  addNetworkServiceProvider,
+                                  updateNetworkServiceProvider,
+                                  listDomains,
+                                  listZones,
+                                  listPods,
+                                  listOsTypes,
+                                  listTemplates,
+                                  updateResourceLimit,
+                                  listRouters,
+                                  listNetworks,
+                                  listClusters,
+                                  listSystemVms,
+                                  listStoragePools,
+                                  listVirtualMachines,
+                                  listLoadBalancerRuleInstances,
+                                  listFirewallRules,
+                                  listVolumes,
+                                  listIsos,
+                                  listAccounts,
+                                  listSnapshotPolicies,
+                                  listDiskOfferings,
+                                  listVlanIpRanges,
+                                  listUsageRecords,
+                                  listNetworkServiceProviders,
+                                  listHosts,
+                                  listPublicIpAddresses,
+                                  listPortForwardingRules,
+                                  listLoadBalancerRules,
+                                  listSnapshots,
+                                  listUsers,
+                                  listEvents,
+                                  listServiceOfferings,
+                                  listVirtualRouterElements,
+                                  listNetworkOfferings,
+                                  listResourceLimits,
+                                  listVPCOfferings)
+
+
+
+
+from marvin.sshClient import SshClient
+from marvin.codes import (PASS, ISOLATED_NETWORK, VPC_NETWORK,
+                          BASIC_ZONE, FAIL, NAT_RULE, STATIC_NAT_RULE)
+import random
+from marvin.lib.utils import *
+from marvin.lib.base import *
+from marvin.codes import PASS
+
+
+# Import System modules
+import time
+
+
+def is_config_suitable(apiclient, name, value):
+    """
+    Ensure if the deployment has the expected `value` for the global setting `name'
+    @return: true if value is set, else false
+    """
+    configs = Configurations.list(apiclient, name=name)
+    assert(
+        configs is not None and isinstance(
+            configs,
+            list) and len(
+            configs) > 0)
+    return configs[0].value == value
+
+
+def wait_for_cleanup(apiclient, configs=None):
+    """Sleeps till the cleanup configs passed"""
+
+    # Configs list consists of the list of global configs
+    if not isinstance(configs, list):
+        return
+    for config in configs:
+        cmd = listConfigurations.listConfigurationsCmd()
+        cmd.name = config
+        cmd.listall = True
+        try:
+            config_descs = apiclient.listConfigurations(cmd)
+        except Exception as e:
+            raise Exception("Failed to fetch configurations: %s" % e)
+
+        if not isinstance(config_descs, list):
+            raise Exception("List configs didn't returned a valid data")
+
+        config_desc = config_descs[0]
+        # Sleep for the config_desc.value time
+        time.sleep(int(config_desc.value))
+    return
+
+
+def add_netscaler(apiclient, zoneid, NSservice):
+    """ Adds Netscaler device and enables NS provider"""
+
+    cmd = listPhysicalNetworks.listPhysicalNetworksCmd()
+    cmd.zoneid = zoneid
+    physical_networks = apiclient.listPhysicalNetworks(cmd)
+    if isinstance(physical_networks, list):
+        physical_network = physical_networks[0]
+
+    cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
+    cmd.name = 'Netscaler'
+    cmd.physicalnetworkid = physical_network.id
+    nw_service_providers = apiclient.listNetworkServiceProviders(cmd)
+
+    if isinstance(nw_service_providers, list):
+        netscaler_provider = nw_service_providers[0]
+    else:
+        cmd1 = addNetworkServiceProvider.addNetworkServiceProviderCmd()
+        cmd1.name = 'Netscaler'
+        cmd1.physicalnetworkid = physical_network.id
+        netscaler_provider = apiclient.addNetworkServiceProvider(cmd1)
+
+    netscaler = NetScaler.add(
+        apiclient,
+        NSservice,
+        physicalnetworkid=physical_network.id
+    )
+    if netscaler_provider.state != 'Enabled':
+        cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd()
+        cmd.id = netscaler_provider.id
+        cmd.state = 'Enabled'
+        apiclient.updateNetworkServiceProvider(cmd)
+
+    return netscaler
+
+
+def get_region(apiclient, region_id=None, region_name=None):
+    '''
+    @name : get_region
+    @Desc : Returns the Region Information for a given region  id or region name
+    @Input : region_name: Name of the Region
+             region_id : Id of the region
+    @Output : 1. Region  Information for the passed inputs else first Region
+              2. FAILED In case the cmd failed
+    '''
+    cmd = listRegions.listRegionsCmd()
+    if region_name is not None:
+        cmd.name = region_name
+    if region_id is not None:
+        cmd.id = region_id
+    cmd_out = apiclient.listRegions(cmd)
+    return FAILED if validateList(cmd_out)[0] != PASS else cmd_out[0]
+
+
+def get_domain(apiclient, domain_id=None, domain_name=None):
+    '''
+    @name : get_domain
+    @Desc : Returns the Domain Information for a given domain id or domain name
+    @Input : domain id : Id of the Domain
+             domain_name : Name of the Domain
+    @Output : 1. Domain  Information for the passed inputs else first Domain
+              2. FAILED In case the cmd failed
+    '''
+    cmd = listDomains.listDomainsCmd()
+
+    if domain_name is not None:
+        cmd.name = domain_name
+    if domain_id is not None:
+        cmd.id = domain_id
+    cmd_out = apiclient.listDomains(cmd)
+    if validateList(cmd_out)[0] != PASS:
+        return FAILED
+    return cmd_out[0]
+
+
+def get_zone(apiclient, zone_name=None, zone_id=None):
+    '''
+    @name : get_zone
+    @Desc :Returns the Zone Information for a given zone id or Zone Name
+    @Input : zone_name: Name of the Zone
+             zone_id : Id of the zone
+    @Output : 1. Zone Information for the passed inputs else first zone
+              2. FAILED In case the cmd failed
+    '''
+    cmd = listZones.listZonesCmd()
+    if zone_name is not None:
+        cmd.name = zone_name
+    if zone_id is not None:
+        cmd.id = zone_id
+
+    cmd_out = apiclient.listZones(cmd)
+
+    if validateList(cmd_out)[0] != PASS:
+        return FAILED
+    '''
+    Check if input zone name and zone id is None,
+    then return first element of List Zones command
+    '''
+    return cmd_out[0]
+
+
+def get_pod(apiclient, zone_id=None, pod_id=None, pod_name=None):
+    '''
+    @name : get_pod
+    @Desc :  Returns the Pod Information for a given zone id or Zone Name
+    @Input : zone_id: Id of the Zone
+             pod_name : Name of the Pod
+             pod_id : Id of the Pod
+    @Output : 1. Pod Information for the pod
+              2. FAILED In case the cmd failed
+    '''
+    cmd = listPods.listPodsCmd()
+
+    if pod_name is not None:
+        cmd.name = pod_name
+    if pod_id is not None:
+        cmd.id = pod_id
+    if zone_id is not None:
+        cmd.zoneid = zone_id
+
+    cmd_out = apiclient.listPods(cmd)
+
+    if validateList(cmd_out)[0] != PASS:
+        return FAILED
+    return cmd_out[0]
+def get_template(
+        apiclient, zone_id=None, ostype_desc=None, template_filter="featured", template_type='BUILTIN',
+        template_id=None, template_name=None, account=None, domain_id=None, project_id=None,
+        hypervisor=None):
+    '''
+    @Name : get_template
+    @Desc : Retrieves the template Information based upon inputs provided
+            Template is retrieved based upon either of the inputs matched
+            condition
+    @Input : returns a template"
+    @Output : FAILED in case of any failure
+              template Information matching the inputs
+    '''
+    cmd = listTemplates.listTemplatesCmd()
+    cmd.templatefilter = template_filter
+    if domain_id is not None:
+        cmd.domainid = domain_id
+    if zone_id is not None:
+        cmd.zoneid = zone_id
+    if template_id is not None:
+        cmd.id = template_id
+    if template_name is not None:
+        cmd.name = template_name
+    if hypervisor is not None:
+        cmd.hypervisor = hypervisor
+    if project_id is not None:
+        cmd.projectid = project_id
+    if account is not None:
+        cmd.account = account
+
+    '''
+    Get the Templates pertaining to the inputs provided
+    '''
+    list_templatesout = apiclient.listTemplates(cmd)
+    if validateList(list_templatesout)[0] != PASS:
+        return FAILED
+
+    for template in list_templatesout:
+        if template.isready and template.templatetype == template_type:
+            return template
+    '''
+    Return default first template, if no template matched
+    '''
+    return list_templatesout[0]
+
+
+def download_systemplates_sec_storage(server, services):
+    """Download System templates on sec storage"""
+
+    try:
+        # Login to management server
+        ssh = SshClient(
+            server["ipaddress"],
+            server["port"],
+            server["username"],
+            server["password"]
+        )
+    except Exception:
+        raise Exception("SSH access failed for server with IP address: %s" %
+                        server["ipaddess"])
+    # Mount Secondary Storage on Management Server
+    cmds = [
+        "mkdir -p %s" % services["mnt_dir"],
+        "mount -t nfs %s:/%s %s" % (
+            services["sec_storage"],
+            services["path"],
+            services["mnt_dir"]
+        ),
+        "%s -m %s -u %s -h %s -F" % (
+            services["command"],
+            services["mnt_dir"],
+            services["download_url"],
+            services["hypervisor"]
+        )
+    ]
+    for c in cmds:
+        result = ssh.execute(c)
+
+    res = str(result)
+
+    # Unmount the Secondary storage
+    ssh.execute("umount %s" % (services["mnt_dir"]))
+
+    if res.count("Successfully installed system VM template") == 1:
+        return
+    else:
+        raise Exception("Failed to download System Templates on Sec Storage")
+    return
+
+
+def wait_for_ssvms(apiclient, zoneid, podid, interval=60):
+    """After setup wait for SSVMs to come Up"""
+
+    time.sleep(interval)
+    timeout = 40
+    while True:
+        list_ssvm_response = list_ssvms(
+            apiclient,
+            systemvmtype='secondarystoragevm',
+            zoneid=zoneid,
+            podid=podid
+        )
+        ssvm = list_ssvm_response[0]
+        if ssvm.state != 'Running':
+            # Sleep to ensure SSVMs are Up and Running
+            time.sleep(interval)
+            timeout = timeout - 1
+        elif ssvm.state == 'Running':
+            break
+        elif timeout == 0:
+            raise Exception("SSVM failed to come up")
+            break
+
+    timeout = 40
+    while True:
+        list_ssvm_response = list_ssvms(
+            apiclient,
+            systemvmtype='consoleproxy',
+            zoneid=zoneid,
+            podid=podid
+        )
+        cpvm = list_ssvm_response[0]
+        if cpvm.state != 'Running':
+            # Sleep to ensure SSVMs are Up and Running
+            time.sleep(interval)
+            timeout = timeout - 1
+        elif cpvm.state == 'Running':
+            break
+        elif timeout == 0:
+            raise Exception("CPVM failed to come up")
+            break
+    return
+
+
+def get_builtin_template_info(apiclient, zoneid):
+    """Returns hypervisor specific infor for templates"""
+
+    list_template_response = Template.list(
+        apiclient,
+        templatefilter='featured',
+        zoneid=zoneid,
+    )
+
+    for b_template in list_template_response:
+        if b_template.templatetype == 'BUILTIN':
+            break
+
+    extract_response = Template.extract(apiclient,
+                                        b_template.id,
+                                        'HTTP_DOWNLOAD',
+                                        zoneid)
+
+    return extract_response.url, b_template.hypervisor, b_template.format
+
+
+def download_builtin_templates(apiclient, zoneid, hypervisor, host,
+                               linklocalip, interval=60):
+    """After setup wait till builtin templates are downloaded"""
+
+    # Change IPTABLES Rules
+    get_process_status(
+        host["ipaddress"],
+        host["port"],
+        host["username"],
+        host["password"],
+        linklocalip,
+        "iptables -P INPUT ACCEPT"
+    )
+    time.sleep(interval)
+    # Find the BUILTIN Templates for given Zone, Hypervisor
+    list_template_response = list_templates(
+        apiclient,
+        hypervisor=hypervisor,
+        zoneid=zoneid,
+        templatefilter='self'
+    )
+
+    if not isinstance(list_template_response, list):
+        raise Exception("Failed to download BUILTIN templates")
+
+    # Ensure all BUILTIN templates are downloaded
+    templateid = None
+    for template in list_template_response:
+        if template.templatetype == "BUILTIN":
+            templateid = template.id
+
+    # Sleep to ensure that template is in downloading state after adding
+    # Sec storage
+    time.sleep(interval)
+    while True:
+        template_response = list_templates(
+            apiclient,
+            id=templateid,
+            zoneid=zoneid,
+            templatefilter='self'
+        )
+        template = template_response[0]
+        # If template is ready,
+        # template.status = Download Complete
+        # Downloading - x% Downloaded
+        # Error - Any other string
+        if template.status == 'Download Complete':
+            break
+
+        elif 'Downloaded' in template.status:
+            time.sleep(interval)
+
+        elif 'Installing' not in template.status:
+            raise Exception("ErrorInDownload")
+
+    return
+
+
+def update_resource_limit(apiclient, resourcetype, account=None,
+                          domainid=None, max=None, projectid=None):
+    """Updates the resource limit to 'max' for given account"""
+
+    cmd = updateResourceLimit.updateResourceLimitCmd()
+    cmd.resourcetype = resourcetype
+    if account:
+        cmd.account = account
+    if domainid:
+        cmd.domainid = domainid
+    if max:
+        cmd.max = max
+    if projectid:
+        cmd.projectid = projectid
+    apiclient.updateResourceLimit(cmd)
+    return
+
+
+def list_os_types(apiclient, **kwargs):
+    """List all os types matching criteria"""
+
+    cmd = listOsTypes.listOsTypesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listOsTypes(cmd))
+
+
+def list_routers(apiclient, **kwargs):
+    """List all Routers matching criteria"""
+
+    cmd = listRouters.listRoutersCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listRouters(cmd))
+
+
+def list_zones(apiclient, **kwargs):
+    """List all Zones matching criteria"""
+
+    cmd = listZones.listZonesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listZones(cmd))
+
+
+def list_networks(apiclient, **kwargs):
+    """List all Networks matching criteria"""
+
+    cmd = listNetworks.listNetworksCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listNetworks(cmd))
+
+
+def list_clusters(apiclient, **kwargs):
+    """List all Clusters matching criteria"""
+
+    cmd = listClusters.listClustersCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listClusters(cmd))
+
+
+def list_ssvms(apiclient, **kwargs):
+    """List all SSVMs matching criteria"""
+
+    cmd = listSystemVms.listSystemVmsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listSystemVms(cmd))
+
+
+def list_storage_pools(apiclient, **kwargs):
+    """List all storage pools matching criteria"""
+
+    cmd = listStoragePools.listStoragePoolsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listStoragePools(cmd))
+
+
+def list_virtual_machines(apiclient, **kwargs):
+    """List all VMs matching criteria"""
+
+    cmd = listVirtualMachines.listVirtualMachinesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVirtualMachines(cmd))
+
+
+def list_hosts(apiclient, **kwargs):
+    """List all Hosts matching criteria"""
+
+    cmd = listHosts.listHostsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listHosts(cmd))
+
+
+def list_configurations(apiclient, **kwargs):
+    """List configuration with specified name"""
+
+    cmd = listConfigurations.listConfigurationsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listConfigurations(cmd))
+
+
+def list_publicIP(apiclient, **kwargs):
+    """List all Public IPs matching criteria"""
+
+    cmd = listPublicIpAddresses.listPublicIpAddressesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listPublicIpAddresses(cmd))
+
+
+def list_nat_rules(apiclient, **kwargs):
+    """List all NAT rules matching criteria"""
+
+    cmd = listPortForwardingRules.listPortForwardingRulesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listPortForwardingRules(cmd))
+
+
+def list_lb_rules(apiclient, **kwargs):
+    """List all Load balancing rules matching criteria"""
+
+    cmd = listLoadBalancerRules.listLoadBalancerRulesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listLoadBalancerRules(cmd))
+
+
+def list_lb_instances(apiclient, **kwargs):
+    """List all Load balancing instances matching criteria"""
+
+    cmd = listLoadBalancerRuleInstances.listLoadBalancerRuleInstancesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listLoadBalancerRuleInstances(cmd))
+
+
+def list_firewall_rules(apiclient, **kwargs):
+    """List all Firewall Rules matching criteria"""
+
+    cmd = listFirewallRules.listFirewallRulesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listFirewallRules(cmd))
+
+
+def list_volumes(apiclient, **kwargs):
+    """List all volumes matching criteria"""
+
+    cmd = listVolumes.listVolumesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVolumes(cmd))
+
+
+def list_isos(apiclient, **kwargs):
+    """Lists all available ISO files."""
+
+    cmd = listIsos.listIsosCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listIsos(cmd))
+
+
+def list_snapshots(apiclient, **kwargs):
+    """List all snapshots matching criteria"""
+
+    cmd = listSnapshots.listSnapshotsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listSnapshots(cmd))
+
+
+def list_templates(apiclient, **kwargs):
+    """List all templates matching criteria"""
+
+    cmd = listTemplates.listTemplatesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listTemplates(cmd))
+
+
+def list_domains(apiclient, **kwargs):
+    """Lists domains"""
+
+    cmd = listDomains.listDomainsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listDomains(cmd))
+
+
+def list_accounts(apiclient, **kwargs):
+    """Lists accounts and provides detailed account information for
+    listed accounts"""
+
+    cmd = listAccounts.listAccountsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listAccounts(cmd))
+
+
+def list_users(apiclient, **kwargs):
+    """Lists users and provides detailed account information for
+    listed users"""
+
+    cmd = listUsers.listUsersCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listUsers(cmd))
+
+
+def list_snapshot_policy(apiclient, **kwargs):
+    """Lists snapshot policies."""
+
+    cmd = listSnapshotPolicies.listSnapshotPoliciesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listSnapshotPolicies(cmd))
+
+
+def list_events(apiclient, **kwargs):
+    """Lists events"""
+
+    cmd = listEvents.listEventsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listEvents(cmd))
+
+
+def list_disk_offering(apiclient, **kwargs):
+    """Lists all available disk offerings."""
+
+    cmd = listDiskOfferings.listDiskOfferingsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listDiskOfferings(cmd))
+
+
+def list_service_offering(apiclient, **kwargs):
+    """Lists all available service offerings."""
+
+    cmd = listServiceOfferings.listServiceOfferingsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listServiceOfferings(cmd))
+
+
+def list_vlan_ipranges(apiclient, **kwargs):
+    """Lists all VLAN IP ranges."""
+
+    cmd = listVlanIpRanges.listVlanIpRangesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVlanIpRanges(cmd))
+
+
+def list_usage_records(apiclient, **kwargs):
+    """Lists usage records for accounts"""
+
+    cmd = listUsageRecords.listUsageRecordsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listUsageRecords(cmd))
+
+
+def list_nw_service_prividers(apiclient, **kwargs):
+    """Lists Network service providers"""
+
+    cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listNetworkServiceProviders(cmd))
+
+
+def list_virtual_router_elements(apiclient, **kwargs):
+    """Lists Virtual Router elements"""
+
+    cmd = listVirtualRouterElements.listVirtualRouterElementsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVirtualRouterElements(cmd))
+
+
+def list_network_offerings(apiclient, **kwargs):
+    """Lists network offerings"""
+
+    cmd = listNetworkOfferings.listNetworkOfferingsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listNetworkOfferings(cmd))
+
+
+def list_resource_limits(apiclient, **kwargs):
+    """Lists resource limits"""
+
+    cmd = listResourceLimits.listResourceLimitsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listResourceLimits(cmd))
+
+
+def list_vpc_offerings(apiclient, **kwargs):
+    """ Lists VPC offerings """
+
+    cmd = listVPCOfferings.listVPCOfferingsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVPCOfferings(cmd))
+
+
+def update_resource_count(apiclient, domainid, accountid=None,
+                          projectid=None, rtype=None):
+    """updates the resource count
+        0     - VM
+        1     - Public IP
+        2     - Volume
+        3     - Snapshot
+        4     - Template
+        5     - Projects
+        6     - Network
+        7     - VPC
+        8     - CPUs
+        9     - RAM
+        10    - Primary (shared) storage (Volumes)
+        11    - Secondary storage (Snapshots, Templates & ISOs)
+    """
+
+    Resources.updateCount(apiclient,
+                          domainid=domainid,
+                          account=accountid if accountid else None,
+                          projectid=projectid if projectid else None,
+                          resourcetype=rtype if rtype else None
+                          )
+    return
+
+def findSuitableHostForMigration(apiclient, vmid):
+    """Returns a suitable host for VM migration"""
+    suitableHost = None
+    try:
+        hosts = Host.listForMigration(apiclient, virtualmachineid=vmid,
+                )
+    except Exception as e:
+        raise Exception("Exception while getting hosts list suitable for migration: %s" % e)
+
+    suitablehosts = []
+    if isinstance(hosts, list) and len(hosts) > 0:
+        suitablehosts = [host for host in hosts if (str(host.resourcestate).lower() == "enabled"\
+                and str(host.state).lower() == "up")]
+        if len(suitablehosts)>0:
+            suitableHost = suitablehosts[0]
+
+    return suitableHost
+
+
+def get_resource_type(resource_id):
+    """Returns resource type"""
+
+    lookup = {0: "VM",
+              1: "Public IP",
+              2: "Volume",
+              3: "Snapshot",
+              4: "Template",
+              5: "Projects",
+              6: "Network",
+              7: "VPC",
+              8: "CPUs",
+              9: "RAM",
+              10: "Primary (shared) storage (Volumes)",
+              11: "Secondary storage (Snapshots, Templates & ISOs)"
+              }
+
+    return lookup[resource_id]
+
+
+
+def get_free_vlan(apiclient, zoneid):
+    """
+    Find an unallocated VLAN outside the range allocated to the physical network.
+
+    @note: This does not guarantee that the VLAN is available for use in
+    the deployment's network gear
+    @return: physical_network, shared_vlan_tag
+    """
+    list_physical_networks_response = PhysicalNetwork.list(
+        apiclient,
+        zoneid=zoneid
+    )
+    assert isinstance(list_physical_networks_response, list)
+    assert len(
+        list_physical_networks_response) > 0, "No physical networks found in zone %s" % zoneid
+
+    physical_network = list_physical_networks_response[0]
+
+    networks = list_networks(apiclient, zoneid=zoneid, type='Shared')
+    usedVlanIds = []
+
+    if isinstance(networks, list) and len(networks) > 0:
+        usedVlanIds = [int(nw.vlan)
+                       for nw in networks if nw.vlan != "untagged"]
+
+    if hasattr(physical_network, "vlan") is False:
+        while True:
+            shared_ntwk_vlan = random.randrange(1, 4095)
+            if shared_ntwk_vlan in usedVlanIds:
+                continue
+            else:
+                break
+    else:
+        vlans = xsplit(physical_network.vlan, ['-', ','])
+
+        assert len(vlans) > 0
+        assert int(vlans[0]) < int(
+            vlans[-1]), "VLAN range  %s was improperly split" % physical_network.vlan
+
+        # Assuming random function will give different integer each time
+        retriesCount = 20
+
+        shared_ntwk_vlan = None
+
+        while True:
+
+            if retriesCount == 0:
+                break
+
+            free_vlan = int(vlans[-1]) + random.randrange(1, 20)
+
+            if free_vlan > 4095:
+                free_vlan = int(vlans[0]) - random.randrange(1, 20)
+            if free_vlan < 0 or (free_vlan in usedVlanIds):
+                retriesCount -= 1
+                continue
+            else:
+                shared_ntwk_vlan = free_vlan
+                break
+
+    return physical_network, shared_ntwk_vlan
+
+
+def setNonContiguousVlanIds(apiclient, zoneid):
+    """
+    Form the non contiguous ranges based on currently assigned range in physical network
+    """
+
+    NonContigVlanIdsAcquired = False
+
+    list_physical_networks_response = PhysicalNetwork.list(
+        apiclient,
+        zoneid=zoneid
+    )
+    assert isinstance(list_physical_networks_response, list)
+    assert len(
+        list_physical_networks_response) > 0, "No physical networks found in zone %s" % zoneid
+
+    for physical_network in list_physical_networks_response:
+
+        vlans = xsplit(physical_network.vlan, ['-', ','])
+
+        assert len(vlans) > 0
+        assert int(vlans[0]) < int(
+            vlans[-1]), "VLAN range  %s was improperly split" % physical_network.vlan
+
+        # Keep some gap between existing vlan and the new vlans which we are going to add
+        # So that they are non contiguous
+
+        non_contig_end_vlan_id = int(vlans[-1]) + 6
+        non_contig_start_vlan_id = int(vlans[0]) - 6
+
+        # Form ranges which are consecutive to existing ranges but not immediately contiguous
+        # There should be gap in between existing range and new non contiguous
+        # ranage
+
+        # If you can't add range after existing range, because it's crossing 4095, then
+        # select VLAN ids before the existing range such that they are greater than 0, and
+        # then add this non contiguoud range
+        vlan = {"partial_range": ["", ""], "full_range": ""}
+
+        if non_contig_end_vlan_id < 4095:
+            vlan["partial_range"][0] = str(
+                non_contig_end_vlan_id - 4) + '-' + str(non_contig_end_vlan_id - 3)
+            vlan["partial_range"][1] = str(
+                non_contig_end_vlan_id - 1) + '-' + str(non_contig_end_vlan_id)
+            vlan["full_range"] = str(
+                non_contig_end_vlan_id - 4) + '-' + str(non_contig_end_vlan_id)
+            NonContigVlanIdsAcquired = True
+
+        elif non_contig_start_vlan_id > 0:
+            vlan["partial_range"][0] = str(
+                non_contig_start_vlan_id) + '-' + str(non_contig_start_vlan_id + 1)
+            vlan["partial_range"][1] = str(
+                non_contig_start_vlan_id + 3) + '-' + str(non_contig_start_vlan_id + 4)
+            vlan["full_range"] = str(
+                non_contig_start_vlan_id) + '-' + str(non_contig_start_vlan_id + 4)
+            NonContigVlanIdsAcquired = True
+
+        else:
+            NonContigVlanIdsAcquired = False
+
+        # If failed to get relevant vlan ids, continue to next physical network
+        # else break from loop as we have hot the non contiguous vlan ids for
+        # the test purpose
+
+        if not NonContigVlanIdsAcquired:
+            continue
+        else:
+            break
+
+    # If even through looping from all existing physical networks, failed to get relevant non
+    # contiguous vlan ids, then fail the test case
+
+    if not NonContigVlanIdsAcquired:
+        return None, None
+
+    return physical_network, vlan
+
+def is_public_ip_in_correct_state(apiclient, ipaddressid, state):
+    """ Check if the given IP is in the correct state (given)
+    and return True/False accordingly"""
+    retriesCount = 10
+    while True:
+        portableips = PublicIPAddress.list(apiclient, id=ipaddressid)
+        assert validateList(portableips)[0] == PASS, "IPs list validation failed"
+        if str(portableips[0].state).lower() == state:
+            break
+        elif retriesCount == 0:
+           return False
+        else:
+            retriesCount -= 1
+            time.sleep(60)
+            continue
+    return True
+
+def setSharedNetworkParams(networkServices, range=20):
+    """Fill up the services dictionary for shared network using random subnet"""
+
+    # @range: range decides the endip. Pass the range as "x" if you want the difference between the startip
+    # and endip as "x"
+    # Set the subnet number of shared networks randomly prior to execution
+    # of each test case to avoid overlapping of ip addresses
+    shared_network_subnet_number = random.randrange(1,254)
+
+    networkServices["gateway"] = "172.16."+str(shared_network_subnet_number)+".1"
+    networkServices["startip"] = "172.16."+str(shared_network_subnet_number)+".2"
+    networkServices["endip"] = "172.16."+str(shared_network_subnet_number)+"."+str(range+1)
+    networkServices["netmask"] = "255.255.255.0"
+    return networkServices
+
+def createEnabledNetworkOffering(apiclient, networkServices):
+    """Create and enable network offering according to the type
+
+       @output: List, containing [ Result,Network Offering,Reason ]
+                 Ist Argument('Result') : FAIL : If exception or assertion error occurs
+                                          PASS : If network offering
+                                          is created and enabled successfully
+                 IInd Argument(Net Off) : Enabled network offering
+                                                In case of exception or
+                                                assertion error, it will be None
+                 IIIrd Argument(Reason) :  Reason for failure,
+                                              default to None
+    """
+    try:
+        resultSet = [FAIL, None, None]
+        # Create network offering
+        network_offering = NetworkOffering.create(apiclient, networkServices, conservemode=False)
+
+        # Update network offering state from disabled to enabled.
+        NetworkOffering.update(network_offering, apiclient, id=network_offering.id,
+                               state="enabled")
+    except Exception as e:
+        resultSet[2] = e
+        return resultSet
+    return [PASS, network_offering, None]
+
+def shouldTestBeSkipped(networkType, zoneType):
+    """Decide which test to skip, according to type of network and zone type"""
+
+    # If network type is isolated or vpc and zone type is basic, then test should be skipped
+    skipIt = False
+    if ((networkType.lower() == str(ISOLATED_NETWORK).lower() or networkType.lower() == str(VPC_NETWORK).lower())
+            and (zoneType.lower() == BASIC_ZONE)):
+        skipIt = True
+    return skipIt
+
+def verifyNetworkState(apiclient, networkid, state):
+    """List networks and check if the network state matches the given state"""
+    try:
+        networks = Network.list(apiclient, id=networkid)
+    except Exception as e:
+        raise Exception("Failed while fetching network list with error: %s" % e)
+    assert validateList(networks)[0] == PASS, "Networks list validation failed, list is %s" % networks
+    assert str(networks[0].state).lower() == state, "network state should be %s, it is %s" % (state, networks[0].state)
+    return
+
+def verifyComputeOfferingCreation(apiclient, computeofferingid):
+    """List Compute offerings by ID and verify that the offering exists"""
+
+    cmd = listServiceOfferings.listServiceOfferingsCmd()
+    cmd.id = computeofferingid
+    serviceOfferings = None
+    try:
+        serviceOfferings = apiclient.listServiceOfferings(cmd)
+    except Exception:
+       return FAIL
+    if not (isinstance(serviceOfferings, list) and len(serviceOfferings) > 0):
+       return FAIL
+    return PASS
+
+def createNetworkRulesForVM(apiclient, virtualmachine, ruletype,
+                            account, networkruledata):
+    """Acquire IP, create Firewall and NAT/StaticNAT rule
+        (associating it with given vm) for that IP"""
+
+    try:
+        public_ip = PublicIPAddress.create(
+                apiclient,accountid=account.name,
+                zoneid=virtualmachine.zoneid,domainid=account.domainid,
+                networkid=virtualmachine.nic[0].networkid)
+
+        FireWallRule.create(
+            apiclient,ipaddressid=public_ip.ipaddress.id,
+            protocol='TCP', cidrlist=[networkruledata["fwrule"]["cidr"]],
+            startport=networkruledata["fwrule"]["startport"],
+            endport=networkruledata["fwrule"]["endport"]
+            )
+
+        if ruletype == NAT_RULE:
+            # Create NAT rule
+            NATRule.create(apiclient, virtualmachine,
+                                 networkruledata["natrule"],ipaddressid=public_ip.ipaddress.id,
+                                 networkid=virtualmachine.nic[0].networkid)
+        elif ruletype == STATIC_NAT_RULE:
+            # Enable Static NAT for VM
+            StaticNATRule.enable(apiclient,public_ip.ipaddress.id,
+                                     virtualmachine.id, networkid=virtualmachine.nic[0].networkid)
+    except Exception as e:
+        [FAIL, e]
+    return [PASS, public_ip]

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/404ac549/tools/marvin/marvin/lib/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/utils.py b/tools/marvin/marvin/lib/utils.py
new file mode 100644
index 0000000..cb5dcfb
--- /dev/null
+++ b/tools/marvin/marvin/lib/utils.py
@@ -0,0 +1,498 @@
+# 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.
+"""Utilities functions
+"""
+
+import marvin
+import os
+import time
+import logging
+import string
+import random
+import imaplib
+import email
+import socket
+import urlparse
+import datetime
+from marvin.cloudstackAPI import cloudstackAPIClient, listHosts, listRouters
+from platform import system
+from marvin.cloudstackException import GetDetailExceptionInfo
+from marvin.sshClient import SshClient
+from marvin.codes import (
+                          SUCCESS,
+                          FAIL,
+                          PASS,
+                          MATCH_NOT_FOUND,
+                          INVALID_INPUT,
+                          EMPTY_LIST,
+                          FAILED)
+
+def restart_mgmt_server(server):
+    """Restarts the management server"""
+
+    try:
+        # Get the SSH client
+        ssh = is_server_ssh_ready(
+            server["ipaddress"],
+            server["port"],
+            server["username"],
+            server["password"],
+        )
+        result = ssh.execute("/etc/init.d/cloud-management restart")
+        res = str(result)
+        # Server Stop - OK
+        # Server Start - OK
+        if res.count("OK") != 2:
+            raise ("ErrorInReboot!")
+    except Exception as e:
+        raise e
+    return
+
+
+def fetch_latest_mail(services, from_mail):
+    """Fetch mail"""
+
+    # Login to mail server to verify email
+    mail = imaplib.IMAP4_SSL(services["server"])
+    mail.login(
+        services["email"],
+        services["password"]
+    )
+    mail.list()
+    mail.select(services["folder"])
+    date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
+
+    result, data = mail.uid(
+        'search',
+        None,
+        '(SENTSINCE {date} HEADER FROM "{mail}")'.format(
+            date=date,
+            mail=from_mail
+        )
+    )
+    # Return False if email is not present
+    if data == []:
+        return False
+
+    latest_email_uid = data[0].split()[-1]
+    result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
+    raw_email = data[0][1]
+    email_message = email.message_from_string(raw_email)
+    result = get_first_text_block(email_message)
+    return result
+
+
+def get_first_text_block(email_message_instance):
+    """fetches first text block from the mail"""
+    maintype = email_message_instance.get_content_maintype()
+    if maintype == 'multipart':
+        for part in email_message_instance.get_payload():
+            if part.get_content_maintype() == 'text':
+                return part.get_payload()
+    elif maintype == 'text':
+        return email_message_instance.get_payload()
+
+
+def random_gen(id=None, size=6, chars=string.ascii_uppercase + string.digits):
+    """Generate Random Strings of variable length"""
+    randomstr = ''.join(random.choice(chars) for x in range(size))
+    if id:
+        return ''.join([id, '-', randomstr])
+    return randomstr
+
+
+def cleanup_resources(api_client, resources):
+    """Delete resources"""
+    for obj in resources:
+        obj.delete(api_client)
+
+
+def is_server_ssh_ready(ipaddress, port, username, password, retries=20, retryinterv=30, timeout=10.0, keyPairFileLocation=None):
+    '''
+    @Name: is_server_ssh_ready
+    @Input: timeout: tcp connection timeout flag,
+            others information need to be added
+    @Output:object for SshClient
+    Name of the function is little misnomer and is not
+              verifying anything as such mentioned
+    '''
+
+    try:
+        ssh = SshClient(
+            host=ipaddress,
+            port=port,
+            user=username,
+            passwd=password,
+            keyPairFiles=keyPairFileLocation,
+            retries=retries,
+            delay=retryinterv,
+            timeout=timeout)
+    except Exception, e:
+        raise Exception("SSH connection has Failed. Waited %ss. Error is %s" % (retries * retryinterv, str(e)))
+    else:
+        return ssh
+
+
+def format_volume_to_ext3(ssh_client, device="/dev/sda"):
+    """Format attached storage to ext3 fs"""
+    cmds = [
+        "echo -e 'n\np\n1\n\n\nw' | fdisk %s" % device,
+        "mkfs.ext3 %s1" % device,
+    ]
+    for c in cmds:
+        ssh_client.execute(c)
+
+
+def fetch_api_client(config_file='datacenterCfg'):
+    """Fetch the Cloudstack API Client"""
+    config = marvin.configGenerator.get_setup_config(config_file)
+    mgt = config.mgtSvr[0]
+    testClientLogger = logging.getLogger("testClient")
+    asyncTimeout = 3600
+    return cloudstackAPIClient.CloudStackAPIClient(
+        marvin.cloudstackConnection.cloudConnection(
+            mgt,
+            asyncTimeout,
+            testClientLogger
+        )
+    )
+
+def get_host_credentials(config, hostip):
+    """Get login information for a host `hostip` (ipv4) from marvin's `config`
+
+    @return the tuple username, password for the host else raise keyerror"""
+    for zone in config.zones:
+        for pod in zone.pods:
+            for cluster in pod.clusters:
+                for host in cluster.hosts:
+                    if str(host.url).startswith('http'):
+                        hostname = urlparse.urlsplit(str(host.url)).netloc
+                    else:
+                        hostname = str(host.url)
+                    try:
+                        if socket.getfqdn(hostip) == socket.getfqdn(hostname):
+                            return host.username, host.password
+                    except socket.error, e:
+                        raise Exception("Unresolvable host %s error is %s" % (hostip, e))
+    raise KeyError("Please provide the marvin configuration file with credentials to your hosts")
+
+
+def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None):
+    """Double hop and returns a process status"""
+
+    #SSH to the machine
+    ssh = SshClient(hostip, port, username, password)
+    if (str(hypervisor).lower() == 'vmware'
+		or str(hypervisor).lower() == 'hyperv'):
+        ssh_command = "ssh -i /var/cloudstack/management/.ssh/id_rsa -ostricthostkeychecking=no "
+    else:
+        ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+
+    ssh_command = ssh_command +\
+                  "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % (
+                      linklocalip,
+                      process)
+
+    # Double hop into router
+    timeout = 5
+    # Ensure the SSH login is successful
+    while True:
+        res = ssh.execute(ssh_command)
+
+        if res[0] != "Host key verification failed.":
+            break
+        elif timeout == 0:
+            break
+
+        time.sleep(5)
+        timeout = timeout - 1
+    return res
+
+
+def isAlmostEqual(first_digit, second_digit, range=0):
+    digits_equal_within_range = False
+
+    try:
+        if ((first_digit - range) < second_digit < (first_digit + range)):
+            digits_equal_within_range = True
+    except Exception as e:
+        raise e
+    return digits_equal_within_range
+
+
+def xsplit(txt, seps):
+    """
+    Split a string in `txt` by list of delimiters in `seps`
+    @param txt: string to split
+    @param seps: list of separators
+    @return: list of split units
+    """
+    default_sep = seps[0]
+    for sep in seps[1:]: # we skip seps[0] because that's the default separator
+        txt = txt.replace(sep, default_sep)
+    return [i.strip() for i in txt.split(default_sep)]
+
+def get_hypervisor_type(apiclient):
+
+    """Return the hypervisor type of the hosts in setup"""
+
+    cmd = listHosts.listHostsCmd()
+    cmd.type = 'Routing'
+    cmd.listall = True
+    hosts = apiclient.listHosts(cmd)
+    hosts_list_validation_result = validateList(hosts)
+    assert hosts_list_validation_result[0] == PASS, "host list validation failed"
+    return hosts_list_validation_result[1].hypervisor
+
+def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid):
+    """
+    Checks whether a snapshot with id (not UUID) `snapshotid` is present on the nfs storage
+
+    @param apiclient: api client connection
+    @param @dbconn:  connection to the cloudstack db
+    @param config: marvin configuration file
+    @param zoneid: uuid of the zone on which the secondary nfs storage pool is mounted
+    @param snapshotid: uuid of the snapshot
+    @return: True if snapshot is found, False otherwise
+    """
+    # snapshot extension to be appended to the snapshot path obtained from db
+    snapshot_extensions = {"vmware": ".ovf",
+                            "kvm": "",
+                            "xenserver": ".vhd",
+                            "simulator":""}
+
+    qresultset = dbconn.execute(
+                        "select id from snapshots where uuid = '%s';" \
+                        % str(snapshotid)
+                        )
+    if len(qresultset) == 0:
+        raise Exception(
+            "No snapshot found in cloudstack with id %s" % snapshotid)
+
+
+    snapshotid = qresultset[0][0]
+    qresultset = dbconn.execute(
+        "select install_path,store_id from snapshot_store_ref where snapshot_id='%s' and store_role='Image';" % snapshotid
+    )
+
+    assert isinstance(qresultset, list), "Invalid db query response for snapshot %s" % snapshotid
+
+    if len(qresultset) == 0:
+        #Snapshot does not exist
+        return False
+
+    from base import ImageStore
+    #pass store_id to get the exact storage pool where snapshot is stored
+    secondaryStores = ImageStore.list(apiclient, zoneid=zoneid, id=int(qresultset[0][1]))
+
+    assert isinstance(secondaryStores, list), "Not a valid response for listImageStores"
+    assert len(secondaryStores) != 0, "No image stores found in zone %s" % zoneid
+
+    secondaryStore = secondaryStores[0]
+
+    if str(secondaryStore.providername).lower() != "nfs":
+        raise Exception(
+            "is_snapshot_on_nfs works only against nfs secondary storage. found %s" % str(secondaryStore.providername))
+
+    hypervisor = get_hypervisor_type(apiclient)
+    # append snapshot extension based on hypervisor, to the snapshot path
+    snapshotPath = str(qresultset[0][0]) + snapshot_extensions[str(hypervisor).lower()]
+
+    nfsurl = secondaryStore.url
+    from urllib2 import urlparse
+    parse_url = urlparse.urlsplit(nfsurl, scheme='nfs')
+    host, path = parse_url.netloc, parse_url.path
+
+    if not config.mgtSvr:
+        raise Exception("Your marvin configuration does not contain mgmt server credentials")
+    mgtSvr, user, passwd = config.mgtSvr[0].mgtSvrIp, config.mgtSvr[0].user, config.mgtSvr[0].passwd
+
+    try:
+        ssh_client = SshClient(
+            mgtSvr,
+            22,
+            user,
+            passwd
+        )
+        cmds = [
+                "mkdir -p %s /mnt/tmp",
+                "mount -t %s %s%s /mnt/tmp" % (
+                    'nfs',
+                    host,
+                    path,
+                    ),
+                "test -f %s && echo 'snapshot exists'" % (
+                    os.path.join("/mnt/tmp", snapshotPath)
+                    ),
+            ]
+
+        for c in cmds:
+            result = ssh_client.execute(c)
+
+        # Unmount the Sec Storage
+        cmds = [
+                "cd",
+                "umount /mnt/tmp",
+            ]
+        for c in cmds:
+            ssh_client.execute(c)
+    except Exception as e:
+        raise Exception("SSH failed for management server: %s - %s" %
+                      (config.mgtSvr[0].mgtSvrIp, e))
+    return 'snapshot exists' in result
+
+def validateList(inp):
+    """
+    @name: validateList
+    @Description: 1. A utility function to validate
+                 whether the input passed is a list
+              2. The list is empty or not
+              3. If it is list and not empty, return PASS and first element
+              4. If not reason for FAIL
+        @Input: Input to be validated
+        @output: List, containing [ Result,FirstElement,Reason ]
+                 Ist Argument('Result') : FAIL : If it is not a list
+                                          If it is list but empty
+                                         PASS : If it is list and not empty
+                 IInd Argument('FirstElement'): If it is list and not empty,
+                                           then first element
+                                            in it, default to None
+                 IIIrd Argument( 'Reason' ):  Reason for failure ( FAIL ),
+                                              default to None.
+                                              INVALID_INPUT
+                                              EMPTY_LIST
+    """
+    ret = [FAIL, None, None]
+    if inp is None:
+        ret[2] = INVALID_INPUT
+        return ret
+    if not isinstance(inp, list):
+        ret[2] = INVALID_INPUT
+        return ret
+    if len(inp) == 0:
+        ret[2] = EMPTY_LIST
+        return ret
+    return [PASS, inp[0], None]
+
+def verifyElementInList(inp, toverify, responsevar=None,  pos=0):
+    '''
+    @name: verifyElementInList
+    @Description:
+    1. A utility function to validate
+    whether the input passed is a list.
+    The list is empty or not.
+    If it is list and not empty, verify
+    whether a given element is there in that list or not
+    at a given pos
+    @Input:
+             I   : Input to be verified whether its a list or not
+             II  : Element to verify whether it exists in the list 
+             III : variable name in response object to verify 
+                   default to None, if None, we will verify for the complete 
+                   first element EX: state of response object object
+             IV  : Position in the list at which the input element to verify
+                   default to 0
+    @output: List, containing [ Result,Reason ]
+             Ist Argument('Result') : FAIL : If it is not a list
+                                      If it is list but empty
+                                      PASS : If it is list and not empty
+                                              and matching element was found
+             IIrd Argument( 'Reason' ): Reason for failure ( FAIL ),
+                                        default to None.
+                                        INVALID_INPUT
+                                        EMPTY_LIST
+                                        MATCH_NOT_FOUND
+    '''
+    if toverify is None or toverify == '' \
+       or pos is None or pos < -1 or pos == '':
+        return [FAIL, INVALID_INPUT]
+    out = validateList(inp)
+    if out[0] == FAIL:
+        return [FAIL, out[2]]
+    if len(inp) > pos:
+        if responsevar is None:
+                if inp[pos] == toverify:
+                    return [PASS, None]
+        else:
+                if responsevar in inp[pos].__dict__ and getattr(inp[pos], responsevar) == toverify:
+                    return [PASS, None]
+                else:
+                    return [FAIL, MATCH_NOT_FOUND]
+    else:
+        return [FAIL, MATCH_NOT_FOUND]
+
+def checkVolumeSize(ssh_handle=None,
+                    volume_name="/dev/sda",
+                    cmd_inp="/sbin/fdisk -l | grep Disk",
+                    size_to_verify=0):
+    '''
+    @Name : getDiskUsage
+    @Desc : provides facility to verify the volume size against the size to verify
+    @Input: 1. ssh_handle : machine against which to execute the disk size cmd
+            2. volume_name : The name of the volume against which to verify the size
+            3. cmd_inp : Input command used to veify the size
+            4. size_to_verify: size against which to compare.
+    @Output: Returns FAILED in case of an issue, else SUCCESS
+    '''
+    try:
+        if ssh_handle is None or cmd_inp is None or volume_name is None:
+            return INVALID_INPUT
+
+        cmd = cmd_inp
+        '''
+        Retrieve the cmd output
+        '''
+        if system().lower() != "windows":
+            fdisk_output = ssh_handle.runCommand(cmd_inp)
+            if fdisk_output["status"] != SUCCESS:
+                return FAILED
+            temp_out = fdisk_output["stdout"]
+            for line in temp_out.split("\n"):
+                if volume_name in line:
+                    parts = line.split()
+                    if str(parts[-2]) == str(size_to_verify):
+                        return [SUCCESS,str(parts[-2])]
+            return [FAILED,"Volume Not Found"]
+    except Exception, e:
+        print "\n Exception Occurred under getDiskUsage: " \
+              "%s" %GetDetailExceptionInfo(e)
+        return [FAILED,GetDetailExceptionInfo(e)]
+
+        
+def verifyRouterState(apiclient, routerid, allowedstates):
+    """List the router and verify that its state is in allowed states
+    @output: List, containing [Result, Reason]
+             Ist Argument ('Result'): FAIL: If router state is not
+                                                in allowed states
+                                          PASS: If router state is in
+                                                allowed states"""
+
+    try:
+        cmd = listRouters.listRoutersCmd()
+        cmd.id = routerid
+        cmd.listall = True
+        routers = apiclient.listRouters(cmd)
+    except Exception as e:
+        return [FAIL, e]
+    listvalidationresult = validateList(routers)
+    if listvalidationresult[0] == FAIL:
+        return [FAIL, listvalidationresult[2]]
+    if routers[0].redundantstate not in allowedstates:
+        return [FAIL, "Redundant state of the router should be in %s but is %s" %
+            (allowedstates, routers[0].redundantstate)]
+    return [PASS, None]
+        
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/404ac549/tools/marvin/marvin/marvinInit.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinInit.py b/tools/marvin/marvin/marvinInit.py
index f722058..c35fec6 100644
--- a/tools/marvin/marvin/marvinInit.py
+++ b/tools/marvin/marvin/marvinInit.py
@@ -15,56 +15,67 @@
 # specific language governing permissions and limitations
 # under the License.
 '''
-@Desc: Initializes the marvin and does required prerequisites
+Initializes the marvin and does required prerequisites
 for starting it.
-1. Parses the configuration file passed to marvin and creates a
-   parsed config
+   1. Parses the configuration file passed to marvin and creates a
+   parsed config.
    2. Initializes the logging required for marvin.All logs are
    now made available under a single timestamped folder.
-   3. Deploys the Data Center based upon input
+   3. Deploys the Data Center based upon input.
 
 '''
-
-from marvin import configGenerator
-from marvin import cloudstackException
+from marvin.configGenerator import getSetupConfig
 from marvin.marvinLog import MarvinLog
-from marvin.deployDataCenter import deployDataCenters
+from marvin.deployDataCenter import DeployDataCenters
+from marvin.cloudstackTestClient import CSTestClient
+from marvin.cloudstackException import GetDetailExceptionInfo
 from marvin.codes import(
-    YES,
-    NO,
+    XEN_SERVER,
     SUCCESS,
     FAILED
-    )
-import sys
-import time
+)
 import os
-import logging
-import string
-import random
 
 
 class MarvinInit:
-    def __init__(self, config_file, load_flag, log_folder_path=None):
+
+    def __init__(self, config_file,
+                 deploy_dc_flag=None,
+                 test_mod_name="deploydc",
+                 zone=None,
+                 hypervisor_type=None,
+                 user_logfolder_path=None):
         self.__configFile = config_file
-        self.__loadFlag = load_flag
-        self.__parsedConfig = None
-        self.__logFolderPath = log_folder_path
+        self.__deployFlag = deploy_dc_flag
+        self.__logFolderPath = None
         self.__tcRunLogger = None
+        self.__testModName = test_mod_name
         self.__testClient = None
-        self.__tcRunDebugFile = None
+        self.__tcResultFile = None
+        self.__testDataFilePath = None
+        self.__zoneForTests = zone
+        self.__parsedConfig = None
+        self.__hypervisorType = hypervisor_type
+        self.__userLogFolderPath = user_logfolder_path
 
     def __parseConfig(self):
         '''
+        @Name: __parseConfig
         @Desc : Parses the configuration file passed and assigns
         the parsed configuration
+        @Output : SUCCESS or FAILED
         '''
         try:
-            self.__parsedConfig = configGenerator.\
-                getSetupConfig(self.__configFile)
+            if not os.path.isfile(self.__configFile):
+                print "\n=== Marvin Parse Config Init Failed ==="
+                return FAILED
+            self.__parsedConfig = getSetupConfig(self.__configFile)
+            print "\n=== Marvin Parse Config Successful ==="
             return SUCCESS
-        except Exception, e:
-            print "\n Exception Occurred Under __parseConfig : %s" % str(e)
-            return None
+        except Exception as e:
+            print "\nException Occurred Under __parseConfig : " \
+                  "%s" % GetDetailExceptionInfo(e)
+            return FAILED
 
     def getParsedConfig(self):
         return self.__parsedConfig
@@ -78,33 +89,67 @@ class MarvinInit:
     def getLogger(self):
         return self.__tcRunLogger
 
-    def getDebugFile(self):
-        return self.__tcRunDebugFile
+    def getResultFile(self):
+        '''
+        @Name : getDebugFile
+        @Desc : Creates the result file at a given path.
+        @Output : Returns the Result file to be used for writing
+                test outputs
+        '''
+        if self.__logFolderPath is not None:
+            self.__tcResultFile = open(self.__logFolderPath +
+                                       "/results.txt", "w")
+            return self.__tcResultFile
+
+    def __setHypervisorAndZoneInfo(self):
+        '''
+        @Name : __setHypervisorAndZoneInfo
+        @Desc:  Set the HyperVisor and Zone details;
+                default to XenServer
+        '''
+        try:
+            if not self.__hypervisorType:
+                self.__hypervisorType = XEN_SERVER
+            if not self.__zoneForTests:
+                if self.__parsedConfig:
+                    for zone in self.__parsedConfig.zones:
+                        self.__zoneForTests = zone.name
+                        break
+            return SUCCESS
+        except Exception as e:
+            print "\n Exception Occurred Under init " \
+                  "%s" % GetDetailExceptionInfo(e)
+            return FAILED
 
     def init(self):
         '''
+        @Name : init
         @Desc :Initializes the marvin by
                1. Parsing the configuration and creating a parsed config
                   structure
                2. Creates a timestamped log folder and provides all logs
                   to be dumped there
                3. Creates the DataCenter based upon configuration provided
+        @Output : SUCCESS or FAILED
         '''
         try:
-            if ((self.__parseConfig() is not None) and
-               (self.__initLogging() is not None) and
-               (self.__deployDC() is not None)):
+            if ((self.__parseConfig() != FAILED) and
+                (self.__setHypervisorAndZoneInfo())and
+               (self.__setTestDataPath() != FAILED) and
+               (self.__initLogging() != FAILED) and
+               (self.__createTestClient() != FAILED) and
+               (self.__deployDC() != FAILED)):
                 return SUCCESS
-            else:
-                return FAILED
-        except Exception, e:
-            print "\n Exception Occurred Under init %s" % str(e)
+            return FAILED
+        except Exception as e:
+            print "\n Exception Occurred Under init " \
+                  "%s" % GetDetailExceptionInfo(e)
             return FAILED
 
     def __initLogging(self):
-        try:
-            '''
-            @Desc : 1. Initializes the logging for marvin and so provides
+        '''
+        @Name : __initLogging
+        @Desc : 1. Initializes the logging for marvin and so provides
                     various log features for automation run.
                     2. Initializes all logs to be available under
                     given Folder Path,where all test run logs
@@ -112,58 +157,87 @@ class MarvinInit:
                     3. All logging like exception log,results, run info etc
                      for a given test run are available under a given
                      timestamped folder
-            '''
-            temp_path = "".join(str(time.time()).split("."))
-            if self.__logFolderPath is None:
-                log_config = self.__parsedConfig.logger
-                if log_config is not None:
-                    if log_config.LogFolderPath is not None:
-                        self.logFolderPath = log_config.LogFolderPath + '/' \
-                            + temp_path
-                    else:
-                        self.logFolderPath = temp_path
-                else:
-                    self.logFolderPath = temp_path
-            else:
-                self.logFolderPath = self.__logFolderPath + '/' + temp_path
-            if os.path.exists(self.logFolderPath):
-                self.logFolderPath += ''.join(random.choice(
-                    string.ascii_uppercase +
-                    string.digits for x in range(3)))
-            os.makedirs(self.logFolderPath)
-            '''
-            Log File Paths
-            '''
-            tc_failed_exceptionlog = self.logFolderPath + "/failed_" \
-                                                          "plus_" \
-                                                          "exceptions.txt"
-            tc_run_log = self.logFolderPath + "/runinfo.txt"
-            self.__tcRunDebugFile = open(self.logFolderPath +
-                                         "/results.txt", "w")
-
+        @Output : SUCCESS or FAILED
+        '''
+        try:
             log_obj = MarvinLog("CSLog")
-            self.__tcRunLogger = log_obj.setLogHandler(tc_run_log)
-            log_obj.setLogHandler(tc_failed_exceptionlog,
-                                  log_level=logging.FATAL)
+            if log_obj:
+                ret = log_obj.\
+                    createLogs(self.__testModName,
+                               self.__parsedConfig.logger,
+                               self.__userLogFolderPath)
+                if ret != FAILED:
+                    self.__logFolderPath = log_obj.getLogFolderPath()
+                    self.__tcRunLogger = log_obj.getLogger()
+                    print "\n=== Marvin Init Logging Successful==="
+                    return SUCCESS
+            return FAILED
+        except Exception as e:
+            print "\n Exception Occurred Under __initLogging " \
+                  ":%s" % GetDetailExceptionInfo(e)
+            return FAILED
+
+    def __createTestClient(self):
+        '''
+        @Name : __createTestClient
+        @Desc : Creates the TestClient during init
+                based upon the parameters provided
+        @Output: Returns SUCCESS or FAILED
+        '''
+        try:
+            mgt_details = self.__parsedConfig.mgtSvr[0]
+            dbsvr_details = self.__parsedConfig.dbSvr
+            self.__testClient = CSTestClient(mgt_details, dbsvr_details,
+                                             logger=self.__tcRunLogger,
+                                             test_data_filepath=
+                                             self.__testDataFilePath,
+                                             zone=self.__zoneForTests,
+                                             hypervisor_type=
+                                             self.__hypervisorType)
+            if self.__testClient:
+                return self.__testClient.createTestClient()
+            return FAILED
+        except Exception as e:
+            print "\n Exception Occurred Under __createTestClient : %s" % \
+                  GetDetailExceptionInfo(e)
+            return FAILED
+
+    def __setTestDataPath(self):
+        '''
+        @Name : __setTestDataPath
+        @Desc : Sets the TestData Path for tests to run
+        @Output:Returns SUCCESS or FAILED
+        '''
+        try:
+            if ((self.__parsedConfig.TestData is not None) and
+                    (self.__parsedConfig.TestData.Path is not None)):
+                self.__testDataFilePath = self.__parsedConfig.TestData.Path
+            print "\n=== Marvin Setting TestData Successful==="
             return SUCCESS
-        except Exception, e:
-            print "\n Exception Occurred Under __initLogging :%s" % str(e)
-            return None
+        except Exception as e:
+            print "\nException Occurred Under __setTestDataPath : %s" % \
+                  GetDetailExceptionInfo(e)
+            return FAILED
 
     def __deployDC(self):
+        '''
+        @Name : __deployDC
+        @Desc : Deploy the DataCenter and returns accordingly.
+        @Output: SUCCESS or FAILED
+        '''
         try:
-            '''
-            Deploy the DataCenter and retrieves test client.
-            '''
-            deploy_obj = deployDataCenters(self.__parsedConfig,
-                                           self.__tcRunLogger)
-            if self.__loadFlag:
-                deploy_obj.loadCfg()
-            else:
-                deploy_obj.deploy()
-
-            self.__testClient = deploy_obj.testClient
-            return SUCCESS
-        except Exception, e:
-            print "\n Exception Occurred Under __deployDC : %s" % str(e)
-            return None
+            ret = SUCCESS
+            if self.__deployFlag:
+                deploy_obj = DeployDataCenters(self.__testClient,
+                                               self.__parsedConfig,
+                                               self.__tcRunLogger)
+                ret = deploy_obj.deploy()
+                if ret == SUCCESS:
+                    print "Deploy DC Successful"
+                else:
+                    print "Deploy DC Failed"
+            return ret
+        except Exception as e:
+            print "\n Exception Occurred Under __deployDC : %s" % \
+                  GetDetailExceptionInfo(e)
+            return FAILED

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/404ac549/tools/marvin/marvin/marvinLog.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinLog.py b/tools/marvin/marvin/marvinLog.py
index 76de185..65687aa 100644
--- a/tools/marvin/marvin/marvinLog.py
+++ b/tools/marvin/marvin/marvinLog.py
@@ -20,17 +20,22 @@
 import logging
 import sys
 import time
-from marvin.codes import (NO,
-                          YES
+import os
+from marvin.codes import (SUCCESS,
+                          FAILED
                           )
+from marvin.cloudstackException import GetDetailExceptionInfo
+from marvin.lib.utils import random_gen
 
 
 class MarvinLog:
+
     '''
+    @Name  : MarvinLog
     @Desc  : provides interface for logging to marvin
     @Input : logger_name : name for logger
     '''
-    logFormat = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")
+    logFormat = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
     _instance = None
 
     def __new__(cls, logger_name):
@@ -39,21 +44,39 @@ class MarvinLog:
             return cls._instance
 
     def __init__(self, logger_name):
-        self.loggerName = logger_name
-        self.logger = None
+        '''
+        @Name: __init__
+        @Input: logger_name for logger
+        '''
+        self.__loggerName = logger_name
+        '''
+        Logger for Logging Info
+        '''
+        self.__logger = None
+        '''
+        Log Folder Directory
+        '''
+        self.__logFolderDir = None
         self.__setLogger()
 
     def __setLogger(self):
-        self.logger = logging.getLogger(self.loggerName)
-        self.logger.setLevel(logging.DEBUG)
+        '''
+        @Name : __setLogger
+        @Desc : Sets the Logger and Level
+        '''
+        self.__logger = logging.getLogger(self.__loggerName)
+        self.__logger.setLevel(logging.DEBUG)
 
-    def setLogHandler(self, log_file_path, log_format=None,
-                      log_level=logging.DEBUG):
+    def __setLogHandler(self, log_file_path,
+                        log_format=None,
+                        log_level=logging.DEBUG):
         '''
+        @Name : __setLogHandler
         @Desc: Adds the given Log handler to the current logger
         @Input: log_file_path: Log File Path as where to store the logs
                log_format : Format of log messages to be dumped
                log_level : Determines the level of logging for this logger
+        @Output: SUCCESS if no issues else FAILED
         '''
         try:
             if log_file_path is not None:
@@ -66,8 +89,98 @@ class MarvinLog:
             else:
                 stream.setFormatter(self.__class__.logFormat)
             stream.setLevel(log_level)
-            self.logger.addHandler(stream)
-        except Exception, e:
-            print "\n Exception Occurred Under setLogHandler %s" % str(e)
-        finally:
-            return self.logger
+            self.__logger.addHandler(stream)
+            return SUCCESS
+        except Exception as e:
+            print "\nException Occurred Under " \
+                  "__setLogHandler %s" % GetDetailExceptionInfo(e)
+            return FAILED
+
+    def __cleanPreviousLogs(self, logfolder_to_remove):
+        '''
+        @Name : __cleanPreviousLogs
+        @Desc : Removes the Previous Logs
+        @Return: N\A
+        @Input: logfolder_to_remove: Path of Log to remove
+        '''
+        try:
+            if os.path.isdir(logfolder_to_remove):
+                os.rmdir(logfolder_to_remove)
+        except Exception as e:
+            print "\n Exception Occurred Under __cleanPreviousLogs :%s" % \
+                  GetDetailExceptionInfo(e)
+            return FAILED
+
+    def getLogger(self):
+        '''
+        @Name:getLogger
+        @Desc : Returns the Logger
+        '''
+        return self.__logger
+
+    def getLogFolderPath(self):
+        '''
+        @Name : getLogFolderPath
+        @Desc : Returns the final log directory path for marvin run
+        '''
+        return self.__logFolderDir
+
+    def createLogs(self,
+                   test_module_name=None,
+                   log_cfg=None,
+                   user_provided_logpath=None):
+        '''
+        @Name : createLogs
+        @Desc : Gets the Logger with file paths initialized and created
+        @Inputs :test_module_name: Test Module Name to use for logs while
+                 creating log folder path
+                 log_cfg: Log Configuration provided inside of
+                 Configuration
+                 user_provided_logpath:LogPath provided by user
+                                       If user provided log path
+                                       is available, then one in cfg
+                                       will  not be picked up.
+        @Output : SUCCESS\FAILED
+        '''
+        try:
+            temp_ts = time.strftime("%b_%d_%Y_%H_%M_%S",
+                                    time.localtime())
+            if test_module_name is None:
+                temp_path = temp_ts + "_" + random_gen()
+            else:
+                temp_path = str(test_module_name) + \
+                    "__" + str(temp_ts) + "_" + random_gen()
+
+            if user_provided_logpath:
+                temp_dir = user_provided_logpath
+            elif ((log_cfg is not None) and
+                    ('LogFolderPath' in log_cfg.__dict__.keys()) and
+                    (log_cfg.__dict__.get('LogFolderPath') is not None)):
+                temp_dir = \
+                    log_cfg.__dict__.get('LogFolderPath') + "/MarvinLogs"
+
+            self.__logFolderDir = temp_dir + "//" + temp_path
+            print "\n==== Log Folder Path: %s. " \
+                  "All logs will be available here ====" \
+                  % str(self.__logFolderDir)
+            os.makedirs(self.__logFolderDir)
+
+            '''
+            Log File Paths
+            1. FailedExceptionLog
+            2. RunLog contains the complete Run Information for Test Run
+            3. ResultFile contains the TC result information for Test Run
+            '''
+            tc_failed_exception_log = \
+                self.__logFolderDir + "/failed_plus_exceptions.txt"
+            tc_run_log = self.__logFolderDir + "/runinfo.txt"
+            if self.__setLogHandler(tc_run_log,
+                                    log_level=logging.DEBUG) != FAILED:
+                self.__setLogHandler(tc_failed_exception_log,
+                                     log_level=logging.FATAL)
+                return SUCCESS
+            return FAILED
+        except Exception as e:
+            print "\n Exception Occurred Under createLogs :%s" % \
+                  GetDetailExceptionInfo(e)
+            return FAILED


Mime
View raw message