You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ts...@apache.org on 2013/11/18 09:50:19 UTC
[12/50] [abbrv] marvin-refactor: moving old integration libraries to
legacy
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fac014d2/tools/marvin/marvin/legacy/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/legacy/common.py b/tools/marvin/marvin/legacy/common.py
new file mode 100644
index 0000000..63bff7c
--- /dev/null
+++ b/tools/marvin/marvin/legacy/common.py
@@ -0,0 +1,739 @@
+# 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 *
+from marvin.remoteSSHClient import remoteSSHClient
+from marvin.legacy.utils import *
+from marvin.integration.lib.base import Configurations
+
+#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'
+ response = apiclient.updateNetworkServiceProvider(cmd)
+
+ return netscaler
+
+def get_region(apiclient, services=None):
+ "Returns a default region"
+
+ cmd = listRegions.listRegionsCmd()
+ if services:
+ if "regionid" in services:
+ cmd.id = services["regionid"]
+
+ regions = apiclient.listRegions(cmd)
+
+ if isinstance(regions, list):
+ assert len(regions) > 0
+ return regions[0]
+ else:
+ raise Exception("Failed to find specified region.")
+
+def get_domain(apiclient, services=None):
+ "Returns a default domain"
+
+ cmd = listDomains.listDomainsCmd()
+ if services:
+ if "domainid" in services:
+ cmd.id = services["domainid"]
+
+ domains = apiclient.listDomains(cmd)
+
+ if isinstance(domains, list):
+ assert len(domains) > 0
+ return domains[0]
+ else:
+ raise Exception("Failed to find specified domain.")
+
+
+def get_zone(apiclient, services=None):
+ "Returns a default zone"
+
+ cmd = listZones.listZonesCmd()
+ if services:
+ if "zoneid" in services:
+ cmd.id = services["zoneid"]
+
+ zones = apiclient.listZones(cmd)
+
+ if isinstance(zones, list):
+ assert len(zones) > 0, "There are no available zones in the deployment"
+ return zones[0]
+ else:
+ raise Exception("Failed to find specified zone.")
+
+
+def get_pod(apiclient, zoneid, services=None):
+ "Returns a default pod for specified zone"
+
+ cmd = listPods.listPodsCmd()
+ cmd.zoneid = zoneid
+
+ if services:
+ if "podid" in services:
+ cmd.id = services["podid"]
+
+ pods = apiclient.listPods(cmd)
+
+ if isinstance(pods, list):
+ assert len(pods) > 0, "No pods found for zone %s"%zoneid
+ return pods[0]
+ else:
+ raise Exception("Exception: Failed to find specified pod.")
+
+
+def get_template(apiclient, zoneid, ostype, services=None):
+ "Returns a template"
+
+ cmd = listOsTypes.listOsTypesCmd()
+ cmd.description = ostype
+ ostypes = apiclient.listOsTypes(cmd)
+
+ if isinstance(ostypes, list):
+ ostypeid = ostypes[0].id
+ else:
+ raise Exception(
+ "Failed to find OS type with description: %s" % ostype)
+
+ cmd = listTemplates.listTemplatesCmd()
+ cmd.templatefilter = 'featured'
+ cmd.zoneid = zoneid
+
+ if services:
+ if "template" in services:
+ cmd.id = services["template"]
+
+ list_templates = apiclient.listTemplates(cmd)
+
+ if isinstance(list_templates, list):
+ assert len(list_templates) > 0, "received empty response on template of type %s"%ostype
+ for template in list_templates:
+ if template.ostypeid == ostypeid:
+ return template
+ elif template.isready:
+ return template
+
+ raise Exception("Exception: Failed to find template with OSTypeID: %s" %
+ ostypeid)
+ return
+
+
+def download_systemplates_sec_storage(server, services):
+ """Download System templates on sec storage"""
+
+ try:
+ # Login to management server
+ ssh = remoteSSHClient(
+ server["ipaddress"],
+ server["port"],
+ server["username"],
+ server["password"]
+ )
+ except Exception:
+ raise Exception("SSH access failted 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 find_suitable_host(apiclient, vm):
+ """Returns a suitable host for VM migration"""
+
+ hosts = Host.list(apiclient,
+ virtualmachineid=vm.id,
+ listall=True)
+
+ if isinstance(hosts, list):
+ assert len(hosts) > 0, "List host should return valid response"
+ else:
+ raise Exception("Exception: List host should return valid response")
+ return hosts[0]
+
+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_portable_ip_range_services(config):
+ """ Reads config values related to portable ip and fills up
+ services accordingly"""
+
+ services = {}
+ attributeError = False
+
+ if config.portableIpRange.startip:
+ services["startip"] = config.portableIpRange.startip
+ else:
+ attributeError = True
+
+ if config.portableIpRange.endip:
+ services["endip"] = config.portableIpRange.endip
+ else:
+ attributeError = True
+
+ if config.portableIpRange.netmask:
+ services["netmask"] = config.portableIpRange.netmask
+ else:
+ attributeError = True
+
+ if config.portableIpRange.gateway:
+ services["gateway"] = config.portableIpRange.gateway
+ else:
+ attributeError = True
+
+ if config.portableIpRange.vlan:
+ services["vlan"] = config.portableIpRange.vlan
+
+ if attributeError:
+ services = None
+
+ return services
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fac014d2/tools/marvin/marvin/legacy/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/legacy/utils.py b/tools/marvin/marvin/legacy/utils.py
new file mode 100644
index 0000000..fcfa338
--- /dev/null
+++ b/tools/marvin/marvin/legacy/utils.py
@@ -0,0 +1,354 @@
+# 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 *
+from marvin.remoteSSHClient import remoteSSHClient
+from marvin.codes import *
+
+
+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=10, timeout=30, keyPairFileLocation=None):
+ """Return ssh handle else wait till sshd is running"""
+ try:
+ ssh = remoteSSHClient(
+ host=ipaddress,
+ port=port,
+ user=username,
+ passwd=password,
+ keyPairFileLocation=keyPairFileLocation,
+ retries=retries,
+ delay=timeout)
+ except Exception, e:
+ raise Exception("Failed to bring up ssh service in time. Waited %ss. Error is %s" % (retries * timeout, 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.mgtSvrIp,
+ mgt.port,
+ mgt.apiKey,
+ mgt.securityKey,
+ 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 = remoteSSHClient(hostip, port, username, password)
+ if str(hypervisor).lower() == 'vmware':
+ 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 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
+ """
+
+ from entity import ImageStore, Snapshot
+ secondaryStores = ImageStore.list(apiclient, zoneid=zoneid)
+
+ 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))
+
+ 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 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
+
+ snapshotPath = qresultset[0][0]
+
+ 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 = remoteSSHClient(
+ 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]