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]