class DeployDataCenters(object):
    """
    @Desc : Deploys the Data Center with information provided.
            Once the Deployment is successful, it will export
            the DataCenter settings to an obj file
            ( can be used if wanted to delete the created DC)
    """

    def __init__(self, test_client, cfg):
        self.__test_client = test_client
        self.__config = cfg
        self.__logger = MarvinLog('marvin').getLogger()
        self.__apiClient = None
        self.__cleanUp = {}

    def __persistDcConfig(self):
        try:
            ts = strftime("%b_%d_%Y_%H_%M_%S", localtime())
            dc_file_path = "dc_entries_" + str(ts) + ".obj"
            file_to_write = open(dc_file_path, 'w')
            if file_to_write:
                pickle.dump(self.__cleanUp, file_to_write)
                self.__logger.info("=== Data Center Settings are dumped to %s ===" % dc_file_path)
        except Exception as e:
            self.__logger.exception("=== Persisting DataCenter config failed: %s ===" % e)

    def __cleanAndExit(self):
        try:
            self.__logger.info("=== deploy dc failed, so cleaning the created entries ===")
            if not test_data.get("deleteDC", None):
                self.__logger.info("=== Deploy DC Clean Up flag not set. So, exiting ===")
                exit(1)
            self.__logger.info("=== Deploy DC Failed, So Cleaning to Exit ===")
            remove_dc_obj = DeleteDataCenters(self.__test_client, self.__cleanUp)
            if remove_dc_obj:
                if remove_dc_obj.removeDataCenter() == FAILED:
                    self.__logger.error("=== Removing DataCenter Failed ===")
                else:
                    self.__logger.info("=== Removing DataCenter Successful ===")
        except Exception as e:
            self.__logger.exception("=== Clean up failed: %s ===" % e)
        finally:
            exit(1)

    def __addToCleanUp(self, type, id):
        if type not in self.__cleanUp.keys():
            self.__cleanUp[type] = []
        self.__cleanUp[type].append(id)
        if "order" not in self.__cleanUp.keys():
            self.__cleanUp["order"] = []
        if type not in self.__cleanUp["order"]:
            self.__cleanUp["order"].append(type)

    def addHosts(self, hosts, zoneId, podId, clusterId, hypervisor):
        if hosts is None:
            self.__logger.warn("=== Invalid Hosts Information ===")
            return
        failed_cnt = 0
        for host in hosts:
            try:
                hostcmd = addHost.addHostCmd()
                hostcmd.clusterid = clusterId
                hostcmd.hosttags = host.hosttags
                hostcmd.hypervisor = host.hypervisor
                hostcmd.password = host.password
                hostcmd.podid = podId
                hostcmd.url = host.url
                hostcmd.username = host.username
                hostcmd.zoneid = zoneId
                hostcmd.hypervisor = hypervisor
                ret = self.__apiClient.addHost(hostcmd)
                if ret:
                    self.__logger.info("=== Add Host Successful ===")
                    self.__addToCleanUp("Host", ret[0].id)
            except Exception as e:
                failed_cnt += 1
                self.__logger.exception("=== Adding Host (%s) Failed: %s ===" % (str(host.url), e))
                if failed_cnt == len(hosts):
                    self.__cleanAndExit()

    def createClusters(self, clusters, zoneId, podId, vmwareDc=None):
        try:
            if clusters is None:
                return

            for cluster in clusters:
                clustercmd = addCluster.addClusterCmd()
                clustercmd.clustername = cluster.clustername
                clustercmd.clustertype = cluster.clustertype
                clustercmd.hypervisor = cluster.hypervisor
                clustercmd.password = cluster.password
                clustercmd.podid = podId
                clustercmd.url = cluster.url
                clustercmd.username = cluster.username
                clustercmd.zoneid = zoneId
                clusterresponse = self.__apiClient.addCluster(clustercmd)
                if clusterresponse[0].id:
                    clusterId = clusterresponse[0].id
                    self.__logger.debug(
                        "Cluster Name : %s Id : %s Created Successfully" % (str(cluster.clustername), str(clusterId)))
                    self.__addToCleanUp("Cluster", clusterId)
                self.addHosts(cluster.hosts, zoneId, podId, clusterId, cluster.hypervisor)
                self.waitForHost(zoneId, clusterId)
                self.createPrimaryStorages(cluster.primaryStorages, zoneId, podId, clusterId)
        except Exception as e:
            self.__logger.exception("=== Cluster %s Creation Failed: %s ===" % (str(cluster.clustername), e))
            self.__cleanAndExit()

    def waitForHost(self, zoneId, clusterId):
        """
        Wait for the hosts in the zoneid, clusterid to be up
        2 retries with 30s delay
        """
        try:
            retry, timeout = 2, 30
            cmd = listHosts.listHostsCmd()
            cmd.clusterid, cmd.zoneid = clusterId, zoneId
            hosts = self.__apiClient.listHosts(cmd)
            while retry != 0:
                for host in hosts:
                    if host.state != 'Up':
                        break
                sleep(timeout)
                retry -= 1
        except Exception as e:
            self.__logger.exception("=== List Hosts Failed: %s ===" % e)
            self.__cleanAndExit()

    def createPrimaryStorages(self, primaryStorages, zoneId, podId=None, clusterId=None):
        try:
            if primaryStorages is None:
                return
            for primary in primaryStorages:
                primarycmd = createStoragePool.createStoragePoolCmd()
                if primary.details:
                    for key, value in vars(primary.details).iteritems():
                        primarycmd.details.append({key: value})
                primarycmd.name = primary.name

                primarycmd.tags = primary.tags
                primarycmd.url = primary.url
                if primary.scope == 'zone' or clusterId is None:
                    primarycmd.scope = 'zone'
                    primarycmd.hypervisor = primary.hypervisor
                else:
                    primarycmd.podid = podId
                    primarycmd.clusterid = clusterId
                primarycmd.zoneid = zoneId

                ret = self.__apiClient.createStoragePool(primarycmd)
                if ret.id:
                    self.__logger.info("=== Creating Storage Pool Successful ===")
                    self.__addToCleanUp("StoragePool", ret.id)
        except Exception as e:
            self.__logger.exception("=== Create Storage Pool Failed: %s ===" % e)
            self.__cleanAndExit()

    def createPods(self, pods, zoneId, networkId=None):
        try:
            if pods is None:
                return
            for pod in pods:
                createpod = createPod.createPodCmd()
                createpod.name = pod.name
                createpod.gateway = pod.gateway
                createpod.netmask = pod.netmask
                createpod.startip = pod.startip
                createpod.endip = pod.endip
                createpod.zoneid = zoneId
                createpodResponse = self.__apiClient.createPod(createpod)
                if createpodResponse.id:
                    podId = createpodResponse.id
                    self.__logger.debug("Pod Name : %s Id : %s Created Successfully" % (str(pod.name), str(podId)))
                    self.__addToCleanUp("Pod", podId)
                if pod.guestIpRanges is not None and networkId is not None:
                    self.createVlanIpRanges("Basic", pod.guestIpRanges, zoneId, podId, networkId)
                self.createClusters(pod.clusters, zoneId, podId, vmwareDc=pod.vmwaredc)
        except Exception as e:
            self.__logger.exception("=== Pod: %s Creation Failed: %s ===" % (str(pod.name), e))
            self.__cleanAndExit()

    def createVlanIpRanges(self, mode, ipranges, zoneId, podId=None, networkId=None, forvirtualnetwork=None):
        try:
            if ipranges is None:
                return
            for iprange in ipranges:
                vlanipcmd = createVlanIpRange.createVlanIpRangeCmd()
                vlanipcmd.account = iprange.account
                vlanipcmd.domainid = iprange.domainid
                vlanipcmd.endip = iprange.endip
                vlanipcmd.gateway = iprange.gateway
                vlanipcmd.netmask = iprange.netmask
                vlanipcmd.networkid = networkId
                vlanipcmd.podid = podId
                vlanipcmd.startip = iprange.startip
                vlanipcmd.zoneid = zoneId
                vlanipcmd.vlan = iprange.vlan
                if mode == "Basic":
                    if forvirtualnetwork:
                        vlanipcmd.forvirtualnetwork = "true"
                    else:
                        vlanipcmd.forvirtualnetwork = "false"
                else:
                    vlanipcmd.forvirtualnetwork = "true"
                ret = self.__apiClient.createVlanIpRange(vlanipcmd)
                if ret.id:
                    self.__logger.info("=== Creating Vlan Ip Range Successful ===")
                    self.__addToCleanUp("VlanIpRange", ret.id)
        except Exception as e:
            self.__logger.exception("=== Create Vlan Ip Range Failed: %s ===" % e)
            self.__cleanAndExit()

    def createSecondaryStorages(self, secondaryStorages, zoneId):
        try:
            if secondaryStorages is None:
                return
            for secondary in secondaryStorages:
                secondarycmd = addImageStore.addImageStoreCmd()
                secondarycmd.url = secondary.url
                secondarycmd.provider = secondary.provider
                secondarycmd.details = []

                if secondarycmd.provider.lower() in ('s3', "swift", "smb"):
                    for key, value in vars(secondary.details).iteritems():
                        secondarycmd.details.append({
                            'key': key,
                            'value': value
                        })
                if secondarycmd.provider.lower() in ("nfs", "smb"):
                    secondarycmd.zoneid = zoneId
                ret = self.__apiClient.addImageStore(secondarycmd)
                if ret.id:
                    self.__logger.info("=== Add Image Store Successful ===")
                    self.__addToCleanUp("ImageStore", ret.id)
        except Exception as e:
            self.__logger.exception("=== Add Image Store Failed: %s ===" % e)
            self.__cleanAndExit()

    def createCacheStorages(self, cacheStorages, zoneId):
        try:
            if cacheStorages is None:
                return
            for cache in cacheStorages:
                cachecmd = createSecondaryStagingStore.createSecondaryStagingStoreCmd()
                cachecmd.url = cache.url
                cachecmd.provider = cache.provider
                cachecmd.zoneid = zoneId
                cachecmd.details = []

                if cache.details:
                    for key, value in vars(cache.details).iteritems():
                        cachecmd.details.append({
                            'key': key,
                            'value': value
                        })
                ret = self.__apiClient.createSecondaryStagingStore(cachecmd)
                if ret.id:
                    self.__logger.info("=== Creating Secondary StagingStore Successful ===")
                    self.__addToCleanUp("SecondaryStagingStore", ret.id)
        except Exception as e:
            self.__logger.exception("=== Creating Secondary Staging Storage Failed: %s ===" % e)
            self.__cleanAndExit()

    def createNetworks(self, networks, zoneId):
        try:
            if networks is None:
                return
            for network in networks:
                networkcmd = createNetwork.createNetworkCmd()
                networkcmd.displaytext = network.displaytext
                networkcmd.name = network.name
                networkcmd.networkofferingid = network.networkofferingid
                networkcmd.zoneid = zoneId

                ipranges = network.ipranges
                if ipranges:
                    iprange = ipranges.pop()
                    networkcmd.startip = iprange.startip
                    networkcmd.endip = iprange.endip
                    networkcmd.gateway = iprange.gateway
                    networkcmd.netmask = iprange.netmask
                networkcmdresponse = self.__apiClient.createNetwork(networkcmd)
                if networkcmdresponse.id:
                    networkId = networkcmdresponse.id
                    self.__logger.info(
                        "=== Creating Network Name : %s Id : %s Successful ===" % (str(network.name), str(networkId)))
                    self.__addToCleanUp("Network", networkId)
                    return networkId
        except Exception as e:
            self.__logger.exception("=== Network : %s Creation Failed: %s ===" % (str(network.name), e))
            self.__cleanAndExit()

    def createPhysicalNetwork(self, net, zoneid):
        try:
            phynet = createPhysicalNetwork.createPhysicalNetworkCmd()
            phynet.zoneid = zoneid
            phynet.name = net.name
            phynet.isolationmethods = net.isolationmethods
            phynetwrk = self.__apiClient.createPhysicalNetwork(phynet)
            if phynetwrk.id:
                self.__logger.info("=== Creating Physical Network Name : %s Id : %s Successful ===" % (
                    str(phynet.name), str(phynetwrk.id)))
                self.__addToCleanUp("PhysicalNetwork", phynetwrk.id)
            self.addTrafficTypes(phynetwrk.id, net.traffictypes)
            return phynetwrk
        except Exception as e:
            self.__logger.exception("=== Physical Network Creation Failed: %s ===" % e)
            self.__cleanAndExit()

    def updatePhysicalNetwork(self, networkid, state="Enabled", vlan=None):
        try:
            upnet = updatePhysicalNetwork.updatePhysicalNetworkCmd()
            upnet.id = networkid
            upnet.state = state
            if vlan:
                upnet.vlan = vlan
            ret = self.__apiClient.updatePhysicalNetwork(upnet)
            return ret
        except Exception as e:
            self.__logger.exception("=== Update Physical Network Failed: %s ===" % e)
            self.__cleanAndExit()

    def enableProvider(self, provider_id):
        try:
            upnetprov = \
                updateNetworkServiceProvider.updateNetworkServiceProviderCmd()
            upnetprov.id = provider_id
            upnetprov.state = "Enabled"
            ret = self.__apiClient.updateNetworkServiceProvider(upnetprov)
            if ret.id:
                self.__logger.info("=== Update Network Service Provider Successfull ===")
        except Exception as e:
            self.__logger.exception("=== Update Network Service Provider Failed: %s ===" % e)
            self.__cleanAndExit()

    def configureProviders(self, phynetwrk, providers):
        """
        We will enable the virtualrouter elements for all zones.
        """
        try:
            for provider in providers:
                pnetprov = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
                pnetprov.physicalnetworkid = phynetwrk.id
                pnetprov.state = "Disabled"
                pnetprov.name = provider.name
                pnetprovres = self.__apiClient.listNetworkServiceProviders(
                    pnetprov)
                if pnetprovres and len(pnetprovres) > 0:
                    if provider.name == 'VirtualRouter' or provider.name == 'VpcVirtualRouter':
                        vrprov = listVirtualRouterElements.listVirtualRouterElementsCmd()
                        vrprov.nspid = pnetprovres[0].id
                        vrprovresponse = self.__apiClient.listVirtualRouterElements(vrprov)
                        vrprovid = vrprovresponse[0].id
                        vrconfig = configureVirtualRouterElement.configureVirtualRouterElementCmd()
                        vrconfig.enabled = "true"
                        vrconfig.id = vrprovid
                        self.__apiClient.configureVirtualRouterElement(vrconfig)
                        self.enableProvider(pnetprovres[0].id)
                    elif provider.name == 'InternalLbVm':
                        internallbprov = listInternalLoadBalancerElements.listInternalLoadBalancerElementsCmd()
                        internallbprov.nspid = pnetprovres[0].id
                        internallbresponse = self.__apiClient.listInternalLoadBalancerElements(internallbprov)
                        internallbid = internallbresponse[0].id
                        internallbconfig = configureInternalLoadBalancerElement.configureInternalLoadBalancerElementCmd()
                        internallbconfig.enabled = "true"
                        internallbconfig.id = internallbid
                        self.__apiClient.configureInternalLoadBalancerElement(internallbconfig)
                        self.enableProvider(pnetprovres[0].id)
                    elif provider.name == 'SecurityGroupProvider':
                        self.enableProvider(pnetprovres[0].id)
                elif provider.name in ['NiciraNvp']:
                    netprov = addNetworkServiceProvider.addNetworkServiceProviderCmd()
                    netprov.name = provider.name
                    netprov.physicalnetworkid = phynetwrk.id
                    result = self.__apiClient.addNetworkServiceProvider(
                        netprov)
                    if result.id:
                        self.__logger.info("=== AddNetworkServiceProvider Successful ===")
                        self.__addToCleanUp("NetworkServiceProvider", result.id)
                    if provider.devices is not None:
                        for device in provider.devices:
                            if provider.name == 'NiciraNvp':
                                cmd = addNiciraNvpDevice.addNiciraNvpDeviceCmd()
                                cmd.hostname = device.hostname
                                cmd.username = device.username
                                cmd.password = device.password
                                cmd.transportzoneuuid = device.transportzoneuuid
                                cmd.physicalnetworkid = phynetwrk.id
                                ret = self.__apiClient.addNiciraNvpDevice(cmd)
                                self.__logger.info("=== Add NiciraNvp Successful ===")
                                self.__addToCleanUp("NiciraNvp", ret.id)
                            else:
                                raise InvalidParameterException(
                                    "Device %s doesn't match any know provider type" % device)
                    self.enableProvider(result.id)
        except Exception as e:
            self.__logger.exception("=== List Network Service Providers Failed: %s ===" % e)
            self.__cleanAndExit()

    def addTrafficTypes(self, physical_network_id, traffictypes):
        [self.addTrafficType(physical_network_id, traffic_type) for traffic_type in traffictypes]

    def addTrafficType(self, physical_network_id, traffictype):
        try:
            traffic_type = addTrafficType.addTrafficTypeCmd()
            traffic_type.physicalnetworkid = physical_network_id
            traffic_type.traffictype = traffictype.typ
            traffic_type.kvmnetworklabel = traffictype.kvm \
                if traffictype.kvm is not None else None
            traffic_type.xennetworklabel = traffictype.xen \
                if traffictype.xen is not None else None
            traffic_type.vmwarenetworklabel = traffictype.vmware \
                if traffictype.vmware is not None else None
            traffic_type.simulatorlabel = traffictype.simulator \
                if traffictype.simulator is not None else None
            ret = self.__apiClient.addTrafficType(traffic_type)
            if ret.id:
                self.__logger.info("=== Add TrafficType Successful ===")
                self.__addToCleanUp("TrafficType", ret.id)
                return ret
        except Exception as e:
            self.__logger.exception("=== Add TrafficType Failed: %s ===" % e)
            self.__cleanAndExit()

    def enableZone(self, zoneid, allocation_state="Enabled"):
        try:
            zoneCmd = updateZone.updateZoneCmd()
            zoneCmd.id = zoneid
            zoneCmd.allocationstate = allocation_state
            ret = self.__apiClient.updateZone(zoneCmd)
            if ret.id:
                self.__logger.info("=== Enable Zone Successful ===")
                return ret
        except Exception as e:
            self.__logger.exception("=== Enable Zone Failed: %s ===" % e)
            self.__cleanAndExit()

    def updateZoneDetails(self, zoneid, details):
        try:
            zoneCmd = updateZone.updateZoneCmd()
            zoneCmd.id = zoneid
            zoneCmd.details = details
            ret = self.__apiClient.updateZone(zoneCmd)
            if ret.id:
                self.__logger.info("=== Update Zone Successful ===")
                return ret
        except Exception as e:
            self.__logger.exception("=== Update Zone  Failed: %s ===" % e)
            self.__cleanAndExit()

    def createZone(self, zone, rec=0):
        try:
            zoneresponse = self.__apiClient.createZone(zone)
            if zoneresponse.id:
                self.__logger.info("=== Create Zone Successful ===")
                self.__logger.debug("Zone Name : %s Id : %s " % (str(zone.name), str(zoneresponse.id)))
                self.__addToCleanUp("Zone", zoneresponse.id)
                return zoneresponse.id
            else:
                self.__logger.exception("=== Zone : %s Creation Failed ===" % str(zone.name))
                if not rec:
                    zone.name = zone.name + "_" + random_gen()
                    self.__logger.info("=== Recreating Zone With New Name : %s ===" % zone.name)
                    return self.createZone(zone, 1)
        except Exception as e:
            self.__logger.exception("=== Create Zone Failed: %s ===" % e)
            return FAILED

    def createZones(self, zones):
        try:
            for zone in zones:
                zonecmd = createZone.createZoneCmd()
                zonecmd.dns1 = zone.dns1
                zonecmd.dns2 = zone.dns2
                zonecmd.internaldns1 = zone.internaldns1
                zonecmd.internaldns2 = zone.internaldns2
                zonecmd.name = zone.name
                zonecmd.securitygroupenabled = zone.securitygroupenabled
                zonecmd.localstorageenabled = zone.localstorageenabled
                zonecmd.networktype = zone.networktype
                zonecmd.domain = zone.domain
                if zone.securitygroupenabled != "true":
                    zonecmd.guestcidraddress = zone.guestcidraddress
                zoneId = self.createZone(zonecmd)
                if zoneId == FAILED:
                    self.__logger.error("=== Zone: %s Creation Failed. So Exiting ===" % str(zone.name))
                    self.__cleanAndExit()
                for pnet in zone.physical_networks:
                    phynetwrk = self.createPhysicalNetwork(pnet, zoneId)
                    self.configureProviders(phynetwrk, pnet.providers)
                    self.updatePhysicalNetwork(phynetwrk.id, "Enabled", vlan=pnet.vlan)
                if zone.networktype == "Basic":
                    listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd()
                    if len(filter(lambda x: x.typ == 'Public', zone.physical_networks[0].traffictypes)) > 0:
                        listnetworkoffering.name = "DefaultSharedNetscalerEIPandELBNetworkOffering"
                    else:
                        listnetworkoffering.name = "DefaultSharedNetworkOfferingWithSGService"
                    if zone.networkofferingname is not None:
                        listnetworkoffering.name = zone.networkofferingname
                    listnetworkofferingresponse = self.__apiClient.listNetworkOfferings(listnetworkoffering)
                    guestntwrk = configGenerator.network()
                    guestntwrk.displaytext = "guestNetworkForBasicZone"
                    guestntwrk.name = "guestNetworkForBasicZone"
                    guestntwrk.zoneid = zoneId
                    guestntwrk.networkofferingid = listnetworkofferingresponse[0].id
                    networkid = self.createNetworks([guestntwrk], zoneId)
                    self.createPods(zone.pods, zoneId, networkid)
                    if self.isEipElbZone(zone):
                        self.createVlanIpRanges(zone.networktype, zone.ipranges, zoneId, forvirtualnetwork=True)
                isPureAdvancedZone = (zone.networktype == "Advanced" and zone.securitygroupenabled != "true")
                if isPureAdvancedZone:
                    self.createPods(zone.pods, zoneId)
                    self.createVlanIpRanges(zone.networktype, zone.ipranges, zoneId)
                elif zone.networktype == "Advanced" and zone.securitygroupenabled == "true":
                    listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd()
                    listnetworkoffering.name = "DefaultSharedNetworkOfferingWithSGService"
                    if zone.networkofferingname is not None:
                        listnetworkoffering.name = zone.networkofferingname
                    listnetworkofferingresponse = self.__apiClient.listNetworkOfferings(listnetworkoffering)
                    networkcmd = createNetwork.createNetworkCmd()
                    networkcmd.displaytext = "Shared SG enabled network"
                    networkcmd.name = "Shared SG enabled network"
                    networkcmd.networkofferingid = listnetworkofferingresponse[0].id
                    networkcmd.zoneid = zoneId
                    ipranges = zone.ipranges
                    if ipranges:
                        iprange = ipranges.pop()
                        networkcmd.startip = iprange.startip
                        networkcmd.endip = iprange.endip
                        networkcmd.gateway = iprange.gateway
                        networkcmd.netmask = iprange.netmask
                        networkcmd.vlan = iprange.vlan
                    networkcmdresponse = self.__apiClient.createNetwork(networkcmd)
                    if networkcmdresponse.id:
                        self.__addToCleanUp("Network", networkcmdresponse.id)
                        self.__logger.debug("create Network Successful. NetworkId : %s " % str(networkcmdresponse.id))
                    self.createPods(zone.pods, zoneId, networkcmdresponse.id)
                '''Note: Swift needs cache storage first'''
                self.createCacheStorages(zone.cacheStorages, zoneId)
                self.createSecondaryStorages(zone.secondaryStorages, zoneId)
                if zone.primaryStorages:
                    self.createPrimaryStorages(zone.primaryStorages, zoneId)
                enabled = getattr(zone, 'enabled', 'True')
                if enabled == 'True' or enabled is None:
                    self.enableZone(zoneId, "Enabled")
                details = getattr(zone, 'details')
                if details is not None:
                    det = [d.__dict__ for d in details]
                    self.updateZoneDetails(zoneId, det)
            return
        except Exception as e:
            self.__logger.exception("=== Create Zones Failed: %e ===" % e)

    @staticmethod
    @staticmethod
    def isEipElbZone():
        if zone.networktype == "Basic" and len(
                filter(lambda x: x.typ == 'Public', zone.physical_networks[0].traffictypes)) > 0:
            return True
        return False

    def setClient(self):
        """
        @Name : setClient
        @Desc : Sets the API Client retrieved from test client
        """
        self.__apiClient = self.__test_client.getApiClient()

    def updateConfiguration(self, globalCfg):
        try:
            if globalCfg is None or self.__apiClient is None:
                return None
            for config in globalCfg:
                updateCfg = updateConfiguration.updateConfigurationCmd()
                updateCfg.name = config.name
                updateCfg.value = config.value
                ret = self.__apiClient.updateConfiguration(updateCfg)
                if ret.id:
                    self.__logger.info("=== Update Configuration Successfull ===")
        except Exception as e:
            self.__logger.exception("=== Update Configuration Failed: %s ===" % e)
            self.__cleanAndExit()

    @staticmethod
    def copyAttributesToCommand(source, command):
        map(lambda attr: setattr(command, attr, getattr(source, attr, None)),
            filter(lambda attr: not attr.startswith("__") and attr not in ["required", "isAsync"], dir(command)))

    def deploy(self):
        try:
            self.__logger.info("=== Deploy DC Started ===")
            '''
            Step1 : Set the Client
            '''
            self.setClient()
            '''
            Step2: Update the Configuration
            '''
            self.updateConfiguration(self.__config.globalConfig)
            '''
            Step3 :Deploy the Zone
            '''
            self.createZones(self.__config.zones)
            '''
            Persist the Configuration to an external file post DC creation
            '''
            self.__persistDcConfig()
            self.__logger.info("=== Deploy DC Successful ===")
            return SUCCESS
        except Exception as e:
            self.__logger.exception("=== Deploy DC Failed: %s ===" % e)
            self.__cleanAndExit()
            return FAILED
Esempio n. 2
0
class DeployDataCenters(object):
    """
    @Desc : Deploys the Data Center with information provided.
            Once the Deployment is successful, it will export
            the DataCenter settings to an obj file
            ( can be used if wanted to delete the created DC)
    """

    def __init__(self, test_client, cfg):
        self.__test_client = test_client
        self.__config = cfg
        self.__logger = MarvinLog('marvin').getLogger()
        self.__apiClient = None
        self.__cleanUp = {}

    def __persistDcConfig(self):
        try:
            ts = strftime("%b_%d_%Y_%H_%M_%S", localtime())
            dc_file_path = "dc_entries_" + str(ts) + ".obj"
            file_to_write = open(dc_file_path, 'w')
            if file_to_write:
                pickle.dump(self.__cleanUp, file_to_write)
                self.__logger.info("=== Data Center Settings are dumped to %s ===" % dc_file_path)
        except Exception as e:
            self.__logger.exception("=== Persisting DataCenter config failed: %s ===" % e)

    def __cleanAndExit(self):
        try:
            self.__logger.info("=== deploy dc failed, so cleaning the created entries ===")
            if not test_data.get("deleteDC", None):
                self.__logger.info("=== Deploy DC Clean Up flag not set. So, exiting ===")
                exit(1)
            self.__logger.info("=== Deploy DC Failed, So Cleaning to Exit ===")
            remove_dc_obj = DeleteDataCenters(self.__test_client, self.__cleanUp)
            if remove_dc_obj:
                if remove_dc_obj.removeDataCenter() == FAILED:
                    self.__logger.error("=== Removing DataCenter Failed ===")
                else:
                    self.__logger.info("=== Removing DataCenter Successful ===")
        except Exception as e:
            self.__logger.exception("=== Clean up failed: %s ===" % e)
        finally:
            exit(1)

    def __addToCleanUp(self, type, id):
        if type not in self.__cleanUp.keys():
            self.__cleanUp[type] = []
        self.__cleanUp[type].append(id)
        if "order" not in self.__cleanUp.keys():
            self.__cleanUp["order"] = []
        if type not in self.__cleanUp["order"]:
            self.__cleanUp["order"].append(type)

    def addHosts(self, hosts, zoneId, podId, clusterId, hypervisor):
        if hosts is None:
            self.__logger.warn("=== Invalid Hosts Information ===")
            return
        failed_cnt = 0
        for host in hosts:
            try:
                hostcmd = addHost.addHostCmd()
                hostcmd.clusterid = clusterId
                hostcmd.hosttags = host.hosttags
                hostcmd.hypervisor = host.hypervisor
                hostcmd.password = host.password
                hostcmd.podid = podId
                hostcmd.url = host.url
                hostcmd.username = host.username
                hostcmd.zoneid = zoneId
                hostcmd.hypervisor = hypervisor
                ret = self.__apiClient.addHost(hostcmd)
                if ret:
                    self.__logger.info("=== Add Host Successful ===")
                    self.__addToCleanUp("Host", ret[0].id)
            except Exception as e:
                failed_cnt += 1
                self.__logger.exception("=== Adding Host (%s) Failed: %s ===" % (str(host.url), e))
                if failed_cnt == len(hosts):
                    self.__cleanAndExit()

    def createClusters(self, clusters, zoneId, podId, vmwareDc=None):
        try:
            if clusters is None:
                return

            for cluster in clusters:
                clustercmd = addCluster.addClusterCmd()
                clustercmd.clustername = cluster.clustername
                clustercmd.clustertype = cluster.clustertype
                clustercmd.hypervisor = cluster.hypervisor
                clustercmd.password = cluster.password
                clustercmd.podid = podId
                clustercmd.url = cluster.url
                clustercmd.username = cluster.username
                clustercmd.zoneid = zoneId
                clusterresponse = self.__apiClient.addCluster(clustercmd)
                if clusterresponse[0].id:
                    clusterId = clusterresponse[0].id
                    self.__logger.debug(
                        "Cluster Name : %s Id : %s Created Successfully" % (str(cluster.clustername), str(clusterId)))
                    self.__addToCleanUp("Cluster", clusterId)
                self.addHosts(cluster.hosts, zoneId, podId, clusterId, cluster.hypervisor)
                self.waitForHost(zoneId, clusterId)
                self.createPrimaryStorages(cluster.primaryStorages, zoneId, podId, clusterId)
        except Exception as e:
            self.__logger.exception("=== Cluster %s Creation Failed: %s ===" % (str(cluster.clustername), e))
            self.__cleanAndExit()

    def waitForHost(self, zoneId, clusterId):
        """
        Wait for the hosts in the zoneid, clusterid to be up
        2 retries with 30s delay
        """
        try:
            retry, timeout = 2, 30
            cmd = listHosts.listHostsCmd()
            cmd.clusterid, cmd.zoneid = clusterId, zoneId
            hosts = self.__apiClient.listHosts(cmd)
            while retry != 0:
                for host in hosts:
                    if host.state != 'Up':
                        break
                sleep(timeout)
                retry -= 1
        except Exception as e:
            self.__logger.exception("=== List Hosts Failed: %s ===" % e)
            self.__cleanAndExit()

    def createPrimaryStorages(self, primaryStorages, zoneId, podId=None, clusterId=None):
        try:
            if primaryStorages is None:
                return
            for primary in primaryStorages:
                primarycmd = createStoragePool.createStoragePoolCmd()
                if primary.details:
                    for key, value in vars(primary.details).iteritems():
                        primarycmd.details.append({key: value})
                primarycmd.name = primary.name

                primarycmd.tags = primary.tags
                primarycmd.url = primary.url
                if primary.scope == 'zone' or clusterId is None:
                    primarycmd.scope = 'zone'
                    primarycmd.hypervisor = primary.hypervisor
                else:
                    primarycmd.podid = podId
                    primarycmd.clusterid = clusterId
                primarycmd.zoneid = zoneId

                ret = self.__apiClient.createStoragePool(primarycmd)
                if ret.id:
                    self.__logger.info("=== Creating Storage Pool Successful ===")
                    self.__addToCleanUp("StoragePool", ret.id)
        except Exception as e:
            self.__logger.exception("=== Create Storage Pool Failed: %s ===" % e)
            self.__cleanAndExit()

    def createPods(self, pods, zoneId, networkId=None):
        try:
            if pods is None:
                return
            for pod in pods:
                createpod = createPod.createPodCmd()
                createpod.name = pod.name
                createpod.gateway = pod.gateway
                createpod.netmask = pod.netmask
                createpod.startip = pod.startip
                createpod.endip = pod.endip
                createpod.zoneid = zoneId
                createpodResponse = self.__apiClient.createPod(createpod)
                if createpodResponse.id:
                    podId = createpodResponse.id
                    self.__logger.debug("Pod Name : %s Id : %s Created Successfully" % (str(pod.name), str(podId)))
                    self.__addToCleanUp("Pod", podId)
                if pod.guestIpRanges is not None and networkId is not None:
                    self.createVlanIpRanges("Basic", pod.guestIpRanges, zoneId, podId, networkId)
                self.createClusters(pod.clusters, zoneId, podId, vmwareDc=pod.vmwaredc)
        except Exception as e:
            self.__logger.exception("=== Pod: %s Creation Failed: %s ===" % (str(pod.name), e))
            self.__cleanAndExit()

    def createVlanIpRanges(self, mode, ipranges, zoneId, podId=None, networkId=None, forvirtualnetwork=None):
        try:
            if ipranges is None:
                return
            for iprange in ipranges:
                vlanipcmd = createVlanIpRange.createVlanIpRangeCmd()
                vlanipcmd.account = iprange.account
                vlanipcmd.domainid = iprange.domainid
                vlanipcmd.endip = iprange.endip
                vlanipcmd.gateway = iprange.gateway
                vlanipcmd.netmask = iprange.netmask
                vlanipcmd.networkid = networkId
                vlanipcmd.podid = podId
                vlanipcmd.startip = iprange.startip
                vlanipcmd.zoneid = zoneId
                vlanipcmd.vlan = iprange.vlan
                if mode == "Basic":
                    if forvirtualnetwork:
                        vlanipcmd.forvirtualnetwork = "true"
                    else:
                        vlanipcmd.forvirtualnetwork = "false"
                else:
                    vlanipcmd.forvirtualnetwork = "true"
                ret = self.__apiClient.createVlanIpRange(vlanipcmd)
                if ret.id:
                    self.__logger.info("=== Creating Vlan Ip Range Successful ===")
                    self.__addToCleanUp("VlanIpRange", ret.id)
        except Exception as e:
            self.__logger.exception("=== Create Vlan Ip Range Failed: %s ===" % e)
            self.__cleanAndExit()

    def createSecondaryStorages(self, secondaryStorages, zoneId):
        try:
            if secondaryStorages is None:
                return
            for secondary in secondaryStorages:
                secondarycmd = addImageStore.addImageStoreCmd()
                secondarycmd.url = secondary.url
                secondarycmd.provider = secondary.provider
                secondarycmd.details = []

                if secondarycmd.provider.lower() in ('s3', "swift", "smb"):
                    for key, value in vars(secondary.details).iteritems():
                        secondarycmd.details.append({
                            'key': key,
                            'value': value
                        })
                if secondarycmd.provider.lower() in ("nfs", "smb"):
                    secondarycmd.zoneid = zoneId
                ret = self.__apiClient.addImageStore(secondarycmd)
                if ret.id:
                    self.__logger.info("=== Add Image Store Successful ===")
                    self.__addToCleanUp("ImageStore", ret.id)
        except Exception as e:
            self.__logger.exception("=== Add Image Store Failed: %s ===" % e)
            self.__cleanAndExit()

    def createCacheStorages(self, cacheStorages, zoneId):
        try:
            if cacheStorages is None:
                return
            for cache in cacheStorages:
                cachecmd = createSecondaryStagingStore.createSecondaryStagingStoreCmd()
                cachecmd.url = cache.url
                cachecmd.provider = cache.provider
                cachecmd.zoneid = zoneId
                cachecmd.details = []

                if cache.details:
                    for key, value in vars(cache.details).iteritems():
                        cachecmd.details.append({
                            'key': key,
                            'value': value
                        })
                ret = self.__apiClient.createSecondaryStagingStore(cachecmd)
                if ret.id:
                    self.__logger.info("=== Creating Secondary StagingStore Successful ===")
                    self.__addToCleanUp("SecondaryStagingStore", ret.id)
        except Exception as e:
            self.__logger.exception("=== Creating Secondary Staging Storage Failed: %s ===" % e)
            self.__cleanAndExit()

    def createNetworks(self, networks, zoneId):
        try:
            if networks is None:
                return
            for network in networks:
                networkcmd = createNetwork.createNetworkCmd()
                networkcmd.displaytext = network.displaytext
                networkcmd.name = network.name
                networkcmd.networkofferingid = network.networkofferingid
                networkcmd.zoneid = zoneId

                ipranges = network.ipranges
                if ipranges:
                    iprange = ipranges.pop()
                    networkcmd.startip = iprange.startip
                    networkcmd.endip = iprange.endip
                    networkcmd.gateway = iprange.gateway
                    networkcmd.netmask = iprange.netmask
                networkcmdresponse = self.__apiClient.createNetwork(networkcmd)
                if networkcmdresponse.id:
                    networkId = networkcmdresponse.id
                    self.__logger.info(
                        "=== Creating Network Name : %s Id : %s Successful ===" % (str(network.name), str(networkId)))
                    self.__addToCleanUp("Network", networkId)
                    return networkId
        except Exception as e:
            self.__logger.exception("=== Network : %s Creation Failed: %s ===" % (str(network.name), e))
            self.__cleanAndExit()

    def createPhysicalNetwork(self, net, zoneid):
        try:
            phynet = createPhysicalNetwork.createPhysicalNetworkCmd()
            phynet.zoneid = zoneid
            phynet.name = net.name
            phynet.isolationmethods = net.isolationmethods
            phynetwrk = self.__apiClient.createPhysicalNetwork(phynet)
            if phynetwrk.id:
                self.__logger.info("=== Creating Physical Network Name : %s Id : %s Successful ===" % (
                    str(phynet.name), str(phynetwrk.id)))
                self.__addToCleanUp("PhysicalNetwork", phynetwrk.id)
            self.addTrafficTypes(phynetwrk.id, net.traffictypes)
            return phynetwrk
        except Exception as e:
            self.__logger.exception("=== Physical Network Creation Failed: %s ===" % e)
            self.__cleanAndExit()

    def updatePhysicalNetwork(self, networkid, state="Enabled", vlan=None):
        try:
            upnet = updatePhysicalNetwork.updatePhysicalNetworkCmd()
            upnet.id = networkid
            upnet.state = state
            if vlan:
                upnet.vlan = vlan
            ret = self.__apiClient.updatePhysicalNetwork(upnet)
            return ret
        except Exception as e:
            self.__logger.exception("=== Update Physical Network Failed: %s ===" % e)
            self.__cleanAndExit()

    def enableProvider(self, provider_id):
        try:
            upnetprov = \
                updateNetworkServiceProvider.updateNetworkServiceProviderCmd()
            upnetprov.id = provider_id
            upnetprov.state = "Enabled"
            ret = self.__apiClient.updateNetworkServiceProvider(upnetprov)
            if ret.id:
                self.__logger.info("=== Update Network Service Provider Successfull ===")
        except Exception as e:
            self.__logger.exception("=== Update Network Service Provider Failed: %s ===" % e)
            self.__cleanAndExit()

    def configureProviders(self, phynetwrk, providers):
        """
        We will enable the virtualrouter elements for all zones.
        """
        try:
            for provider in providers:
                pnetprov = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
                pnetprov.physicalnetworkid = phynetwrk.id
                pnetprov.state = "Disabled"
                pnetprov.name = provider.name
                pnetprovres = self.__apiClient.listNetworkServiceProviders(
                    pnetprov)
                if pnetprovres and len(pnetprovres) > 0:
                    if provider.name == 'VirtualRouter' or provider.name == 'VpcVirtualRouter':
                        vrprov = listVirtualRouterElements.listVirtualRouterElementsCmd()
                        vrprov.nspid = pnetprovres[0].id
                        vrprovresponse = self.__apiClient.listVirtualRouterElements(vrprov)
                        vrprovid = vrprovresponse[0].id
                        vrconfig = configureVirtualRouterElement.configureVirtualRouterElementCmd()
                        vrconfig.enabled = "true"
                        vrconfig.id = vrprovid
                        self.__apiClient.configureVirtualRouterElement(vrconfig)
                        self.enableProvider(pnetprovres[0].id)
                    elif provider.name == 'InternalLbVm':
                        internallbprov = listInternalLoadBalancerElements.listInternalLoadBalancerElementsCmd()
                        internallbprov.nspid = pnetprovres[0].id
                        internallbresponse = self.__apiClient.listInternalLoadBalancerElements(internallbprov)
                        internallbid = internallbresponse[0].id
                        internallbconfig = configureInternalLoadBalancerElement.configureInternalLoadBalancerElementCmd()
                        internallbconfig.enabled = "true"
                        internallbconfig.id = internallbid
                        self.__apiClient.configureInternalLoadBalancerElement(internallbconfig)
                        self.enableProvider(pnetprovres[0].id)
                    elif provider.name == 'SecurityGroupProvider':
                        self.enableProvider(pnetprovres[0].id)
                elif provider.name in ['NiciraNvp']:
                    netprov = addNetworkServiceProvider.addNetworkServiceProviderCmd()
                    netprov.name = provider.name
                    netprov.physicalnetworkid = phynetwrk.id
                    result = self.__apiClient.addNetworkServiceProvider(
                        netprov)
                    if result.id:
                        self.__logger.info("=== AddNetworkServiceProvider Successful ===")
                        self.__addToCleanUp("NetworkServiceProvider", result.id)
                    if provider.devices is not None:
                        for device in provider.devices:
                            if provider.name == 'NiciraNvp':
                                cmd = addNiciraNvpDevice.addNiciraNvpDeviceCmd()
                                cmd.hostname = device.hostname
                                cmd.username = device.username
                                cmd.password = device.password
                                cmd.transportzoneuuid = device.transportzoneuuid
                                cmd.physicalnetworkid = phynetwrk.id
                                ret = self.__apiClient.addNiciraNvpDevice(cmd)
                                self.__logger.info("=== Add NiciraNvp Successful ===")
                                self.__addToCleanUp("NiciraNvp", ret.id)
                            else:
                                raise InvalidParameterException(
                                    "Device %s doesn't match any know provider type" % device)
                    self.enableProvider(result.id)
        except Exception as e:
            self.__logger.exception("=== List Network Service Providers Failed: %s ===" % e)
            self.__cleanAndExit()

    def addTrafficTypes(self, physical_network_id, traffictypes):
        [self.addTrafficType(physical_network_id, traffic_type) for traffic_type in traffictypes]

    def addTrafficType(self, physical_network_id, traffictype):
        try:
            traffic_type = addTrafficType.addTrafficTypeCmd()
            traffic_type.physicalnetworkid = physical_network_id
            traffic_type.traffictype = traffictype.typ
            traffic_type.kvmnetworklabel = traffictype.kvm \
                if traffictype.kvm is not None else None
            traffic_type.xennetworklabel = traffictype.xen \
                if traffictype.xen is not None else None
            traffic_type.vmwarenetworklabel = traffictype.vmware \
                if traffictype.vmware is not None else None
            traffic_type.simulatorlabel = traffictype.simulator \
                if traffictype.simulator is not None else None
            ret = self.__apiClient.addTrafficType(traffic_type)
            if ret.id:
                self.__logger.info("=== Add TrafficType Successful ===")
                self.__addToCleanUp("TrafficType", ret.id)
                return ret
        except Exception as e:
            self.__logger.exception("=== Add TrafficType Failed: %s ===" % e)
            self.__cleanAndExit()

    def enableZone(self, zoneid, allocation_state="Enabled"):
        try:
            zoneCmd = updateZone.updateZoneCmd()
            zoneCmd.id = zoneid
            zoneCmd.allocationstate = allocation_state
            ret = self.__apiClient.updateZone(zoneCmd)
            if ret.id:
                self.__logger.info("=== Enable Zone Successful ===")
                return ret
        except Exception as e:
            self.__logger.exception("=== Enable Zone Failed: %s ===" % e)
            self.__cleanAndExit()

    def updateZoneDetails(self, zoneid, details):
        try:
            zoneCmd = updateZone.updateZoneCmd()
            zoneCmd.id = zoneid
            zoneCmd.details = details
            ret = self.__apiClient.updateZone(zoneCmd)
            if ret.id:
                self.__logger.info("=== Update Zone Successful ===")
                return ret
        except Exception as e:
            self.__logger.exception("=== Update Zone  Failed: %s ===" % e)
            self.__cleanAndExit()

    def createZone(self, zone, rec=0):
        try:
            zoneresponse = self.__apiClient.createZone(zone)
            if zoneresponse.id:
                self.__logger.info("=== Create Zone Successful ===")
                self.__logger.debug("Zone Name : %s Id : %s " % (str(zone.name), str(zoneresponse.id)))
                self.__addToCleanUp("Zone", zoneresponse.id)
                return zoneresponse.id
            else:
                self.__logger.exception("=== Zone : %s Creation Failed ===" % str(zone.name))
                if not rec:
                    zone.name = zone.name + "_" + random_gen()
                    self.__logger.info("=== Recreating Zone With New Name : %s ===" % zone.name)
                    return self.createZone(zone, 1)
        except Exception as e:
            self.__logger.exception("=== Create Zone Failed: %s ===" % e)
            return FAILED

    def createZones(self, zones):
        try:
            for zone in zones:
                zonecmd = createZone.createZoneCmd()
                zonecmd.dns1 = zone.dns1
                zonecmd.dns2 = zone.dns2
                zonecmd.internaldns1 = zone.internaldns1
                zonecmd.internaldns2 = zone.internaldns2
                zonecmd.name = zone.name
                zonecmd.securitygroupenabled = zone.securitygroupenabled
                zonecmd.localstorageenabled = zone.localstorageenabled
                zonecmd.networktype = zone.networktype
                zonecmd.domain = zone.domain
                if zone.securitygroupenabled != "true":
                    zonecmd.guestcidraddress = zone.guestcidraddress
                zoneId = self.createZone(zonecmd)
                if zoneId == FAILED:
                    self.__logger.error("=== Zone: %s Creation Failed. So Exiting ===" % str(zone.name))
                    self.__cleanAndExit()
                for pnet in zone.physical_networks:
                    phynetwrk = self.createPhysicalNetwork(pnet, zoneId)
                    self.configureProviders(phynetwrk, pnet.providers)
                    self.updatePhysicalNetwork(phynetwrk.id, "Enabled", vlan=pnet.vlan)
                if zone.networktype == "Basic":
                    listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd()
                    if len(filter(lambda x: x.typ == 'Public', zone.physical_networks[0].traffictypes)) > 0:
                        listnetworkoffering.name = "DefaultSharedNetscalerEIPandELBNetworkOffering"
                    else:
                        listnetworkoffering.name = "DefaultSharedNetworkOfferingWithSGService"
                    if zone.networkofferingname is not None:
                        listnetworkoffering.name = zone.networkofferingname
                    listnetworkofferingresponse = self.__apiClient.listNetworkOfferings(listnetworkoffering)
                    guestntwrk = configGenerator.network()
                    guestntwrk.displaytext = "guestNetworkForBasicZone"
                    guestntwrk.name = "guestNetworkForBasicZone"
                    guestntwrk.zoneid = zoneId
                    guestntwrk.networkofferingid = listnetworkofferingresponse[0].id
                    networkid = self.createNetworks([guestntwrk], zoneId)
                    self.createPods(zone.pods, zoneId, networkid)
                    if self.isEipElbZone(zone):
                        self.createVlanIpRanges(zone.networktype, zone.ipranges, zoneId, forvirtualnetwork=True)
                isPureAdvancedZone = (zone.networktype == "Advanced" and zone.securitygroupenabled != "true")
                if isPureAdvancedZone:
                    self.createPods(zone.pods, zoneId)
                    self.createVlanIpRanges(zone.networktype, zone.ipranges, zoneId)
                elif zone.networktype == "Advanced" and zone.securitygroupenabled == "true":
                    listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd()
                    listnetworkoffering.name = "DefaultSharedNetworkOfferingWithSGService"
                    if zone.networkofferingname is not None:
                        listnetworkoffering.name = zone.networkofferingname
                    listnetworkofferingresponse = self.__apiClient.listNetworkOfferings(listnetworkoffering)
                    networkcmd = createNetwork.createNetworkCmd()
                    networkcmd.displaytext = "Shared SG enabled network"
                    networkcmd.name = "Shared SG enabled network"
                    networkcmd.networkofferingid = listnetworkofferingresponse[0].id
                    networkcmd.zoneid = zoneId
                    ipranges = zone.ipranges
                    if ipranges:
                        iprange = ipranges.pop()
                        networkcmd.startip = iprange.startip
                        networkcmd.endip = iprange.endip
                        networkcmd.gateway = iprange.gateway
                        networkcmd.netmask = iprange.netmask
                        networkcmd.vlan = iprange.vlan
                    networkcmdresponse = self.__apiClient.createNetwork(networkcmd)
                    if networkcmdresponse.id:
                        self.__addToCleanUp("Network", networkcmdresponse.id)
                        self.__logger.debug("create Network Successful. NetworkId : %s " % str(networkcmdresponse.id))
                    self.createPods(zone.pods, zoneId, networkcmdresponse.id)
                '''Note: Swift needs cache storage first'''
                self.createCacheStorages(zone.cacheStorages, zoneId)
                self.createSecondaryStorages(zone.secondaryStorages, zoneId)
                if zone.primaryStorages:
                    self.createPrimaryStorages(zone.primaryStorages, zoneId)
                enabled = getattr(zone, 'enabled', 'True')
                if enabled == 'True' or enabled is None:
                    self.enableZone(zoneId, "Enabled")
                details = getattr(zone, 'details')
                if details is not None:
                    det = [d.__dict__ for d in details]
                    self.updateZoneDetails(zoneId, det)
            return
        except Exception as e:
            self.__logger.exception("=== Create Zones Failed: %e ===" % e)

    def isEipElbZone(self, zone):
        if zone.networktype == "Basic" and len(
                filter(lambda x: x.typ == 'Public', zone.physical_networks[0].traffictypes)) > 0:
            return True
        return False

    def setClient(self):
        """
        @Name : setClient
        @Desc : Sets the API Client retrieved from test client
        """
        self.__apiClient = self.__test_client.getApiClient()

    def updateConfiguration(self, globalCfg):
        try:
            if globalCfg is None or self.__apiClient is None:
                return None
            for config in globalCfg:
                updateCfg = updateConfiguration.updateConfigurationCmd()
                updateCfg.name = config.name
                updateCfg.value = config.value
                ret = self.__apiClient.updateConfiguration(updateCfg)
                if ret.id:
                    self.__logger.info("=== Update Configuration Successfull ===")
        except Exception as e:
            self.__logger.exception("=== Update Configuration Failed: %s ===" % e)
            self.__cleanAndExit()

    @staticmethod
    def copyAttributesToCommand(source, command):
        map(lambda attr: setattr(command, attr, getattr(source, attr, None)),
            filter(lambda attr: not attr.startswith("__") and attr not in ["required", "isAsync"], dir(command)))

    def deploy(self):
        try:
            self.__logger.info("=== Deploy DC Started ===")
            '''
            Step1 : Set the Client
            '''
            self.setClient()
            '''
            Step2: Update the Configuration
            '''
            self.updateConfiguration(self.__config.globalConfig)
            '''
            Step3 :Deploy the Zone
            '''
            self.createZones(self.__config.zones)
            '''
            Persist the Configuration to an external file post DC creation
            '''
            self.__persistDcConfig()
            self.__logger.info("=== Deploy DC Successful ===")
            return SUCCESS
        except Exception as e:
            self.__logger.exception("=== Deploy DC Failed: %s ===" % e)
            self.__cleanAndExit()
            return FAILED
Esempio n. 3
0
class SshClient(object):
    '''
    @Desc : SSH Library for Marvin.
    Facilitates SSH,SCP services to marvin users
    @Input: host: Host to connect
            port: port on host to connect
            user: Username to be used for connecting
            passwd: Password for connection
            retries and delay applies for establishing connection
            timeout : Applies while executing command
    '''
    def __init__(self,
                 host,
                 port,
                 user,
                 passwd,
                 retries=60,
                 delay=10,
                 log_lvl=logging.INFO,
                 keyPairFiles=None,
                 timeout=10.0):
        self.host = None
        self.port = 22
        self.user = user
        self.passwd = passwd
        self.keyPairFiles = keyPairFiles
        self.ssh = SSHClient()
        self.ssh.set_missing_host_key_policy(AutoAddPolicy())
        self.retryCnt = 0
        self.delay = 0
        self.timeout = 3.0
        self.logger = MarvinLog('ssh').getLogger()

        # Check invalid host value and raise exception
        # Atleast host is required for connection
        if host is not None and host != '':
            self.host = host
        if retries is not None and retries > 0:
            self.retryCnt = retries
        if delay is not None and delay > 0:
            self.delay = delay
        if timeout is not None and timeout > 0:
            self.timeout = timeout
        if port is not None and port >= 0:
            self.port = port
        if self.createConnection() == FAILED:
            raise internalError("Connection Failed")

    def execute(self, command):
        stdin, stdout, stderr = self.ssh.exec_command(command)
        output = stdout.readlines()
        errors = stderr.readlines()
        results = []
        if output is not None and len(output) == 0:
            if errors is not None and len(errors) > 0:
                for error in errors:
                    results.append(error.rstrip())

        else:
            for strOut in output:
                results.append(strOut.rstrip())
        self.logger.debug("Executing command via host %s: %s Output: %s" %
                          (str(self.host), command, results))
        return results

    def createConnection(self):
        '''
        @Name: createConnection
        @Desc: Creates an ssh connection for
               retries mentioned,along with sleep mentioned
        @Output: SUCCESS on successful connection
                 FAILED If connection through ssh failed
        '''
        ret = FAILED
        while self.retryCnt >= 0:
            try:
                self.logger.debug(
                    "Trying SSH Connection to host %s on port %s as user %s. RetryCount: %s"
                    %
                    (self.host, str(self.port), self.user, str(self.retryCnt)))
                if self.keyPairFiles is None:
                    self.ssh.connect(hostname=self.host,
                                     port=self.port,
                                     username=self.user,
                                     password=self.passwd,
                                     timeout=self.timeout)
                else:
                    self.ssh.connect(hostname=self.host,
                                     port=self.port,
                                     username=self.user,
                                     password=self.passwd,
                                     key_filename=self.keyPairFiles,
                                     timeout=self.timeout,
                                     look_for_keys=False)
                self.logger.debug(
                    "Connection to host %s on port %s is SUCCESSFUL" %
                    (str(self.host), str(self.port)))
                ret = SUCCESS
                break
            except BadHostKeyException as e:
                self.logger.debug("Failed to create connection: %s" % e)
            except AuthenticationException as e:
                self.logger.debug("Failed to create connection: %s" % e)
            except SSHException as e:
                self.logger.debug("Failed to create connection: %s" % e)
            except socket.error as e:
                self.logger.debug("Failed to create connection: %s" % e)
            except Exception as e:
                self.logger.debug("Failed to create connection: %s" % e)
            finally:
                if self.retryCnt == 0 or ret == SUCCESS:
                    break
                self.retryCnt -= 1
                time.sleep(self.delay)
        return ret

    def runCommand(self, command):
        '''
        @Name: runCommand
        @Desc: Runs a command over ssh and
               returns the result along with status code
        @Input: command to execute
        @Output: 1: status of command executed.
                 SUCCESS : If command execution is successful
                 FAILED    : If command execution has failed
                 2: stdin,stdout,stderr values of command output
        '''
        ret = {
            "status": FAILED,
            "stdin": None,
            "stdout": None,
            "stderr": INVALID_INPUT
        }
        if command is None or command == '':
            return ret
        try:
            stdin, stdout, stderr = self.ssh.exec_command(command,
                                                          timeout=self.timeout)
            if stdout is not None:
                status_check = stdout.channel.recv_exit_status()
                if status_check == 0:
                    ret["status"] = SUCCESS
                ret["stdout"] = stdout.readlines()
                if stderr is not None:
                    ret["stderr"] = stderr.readlines()
        except Exception as e:
            self.logger.debug("Failed to run command: %s" % e)
        finally:
            self.logger.debug(
                "Connection to host %s on port %s is SUCCESSFUL" %
                (str(self.host), command))
            return ret

    def scp(self, srcFile, destPath):
        transport = Transport((self.host, int(self.port)))
        transport.connect(username=self.user, password=self.passwd)
        sftp = SFTPClient.from_transport(transport)
        try:
            sftp.put(srcFile, destPath)
        except IOError as e:
            raise e

    def __del__(self):
        self.close()

    def close(self):
        if self.ssh is not None:
            self.ssh.close()
            self.ssh = None
Esempio n. 4
0
class SshClient(object):
    '''
    @Desc : SSH Library for Marvin.
    Facilitates SSH,SCP services to marvin users
    @Input: host: Host to connect
            port: port on host to connect
            user: Username to be used for connecting
            passwd: Password for connection
            retries and delay applies for establishing connection
            timeout : Applies while executing command
    '''

    def __init__(self, host, port, user, passwd, retries=60, delay=10, log_lvl=logging.INFO, keyPairFiles=None, timeout=10.0):
        self.host = None
        self.port = 22
        self.user = user
        self.passwd = passwd
        self.keyPairFiles = keyPairFiles
        self.ssh = SSHClient()
        self.ssh.set_missing_host_key_policy(AutoAddPolicy())
        self.retryCnt = 0
        self.delay = 0
        self.timeout = 3.0
        self.logger = MarvinLog('ssh').getLogger()

        # Check invalid host value and raise exception
        # Atleast host is required for connection
        if host is not None and host != '':
            self.host = host
        if retries is not None and retries > 0:
            self.retryCnt = retries
        if delay is not None and delay > 0:
            self.delay = delay
        if timeout is not None and timeout > 0:
            self.timeout = timeout
        if port is not None and port >= 0:
            self.port = port
        if self.createConnection() == FAILED:
            raise internalError("Connection Failed")

    def execute(self, command):
        stdin, stdout, stderr = self.ssh.exec_command(command)
        output = stdout.readlines()
        errors = stderr.readlines()
        results = []
        if output is not None and len(output) == 0:
            if errors is not None and len(errors) > 0:
                for error in errors:
                    results.append(error.rstrip())

        else:
            for strOut in output:
                results.append(strOut.rstrip())
        self.logger.debug("Executing command via host %s: %s Output: %s" % (str(self.host), command, results))
        return results

    def createConnection(self):
        '''
        @Name: createConnection
        @Desc: Creates an ssh connection for
               retries mentioned,along with sleep mentioned
        @Output: SUCCESS on successful connection
                 FAILED If connection through ssh failed
        '''
        ret = FAILED
        while self.retryCnt >= 0:
            try:
                self.logger.debug("Trying SSH Connection to host %s on port %s as user %s. RetryCount: %s" %
                                 (self.host, str(self.port), self.user, str(self.retryCnt)))
                if self.keyPairFiles is None:
                    self.ssh.connect(hostname=self.host,
                                     port=self.port,
                                     username=self.user,
                                     password=self.passwd,
                                     timeout=self.timeout)
                else:
                    self.ssh.connect(hostname=self.host,
                                     port=self.port,
                                     username=self.user,
                                     password=self.passwd,
                                     key_filename=self.keyPairFiles,
                                     timeout=self.timeout,
                                     look_for_keys=False
                                     )
                self.logger.debug("Connection to host %s on port %s is SUCCESSFUL" % (str(self.host), str(self.port)))
                ret = SUCCESS
                break
            except BadHostKeyException as e:
                self.logger.debug("Failed to create connection: %s" % e)
            except AuthenticationException as e:
                self.logger.debug("Failed to create connection: %s" % e)
            except SSHException as e:
                self.logger.debug("Failed to create connection: %s" % e)
            except socket.error as e:
                self.logger.debug("Failed to create connection: %s" % e)
            except Exception as e:
                self.logger.debug("Failed to create connection: %s" % e)
            finally:
                if self.retryCnt == 0 or ret == SUCCESS:
                    break
                self.retryCnt -= 1
                time.sleep(self.delay)
        return ret

    def runCommand(self, command):
        '''
        @Name: runCommand
        @Desc: Runs a command over ssh and
               returns the result along with status code
        @Input: command to execute
        @Output: 1: status of command executed.
                 SUCCESS : If command execution is successful
                 FAILED    : If command execution has failed
                 2: stdin,stdout,stderr values of command output
        '''
        ret = {"status": FAILED, "stdin": None, "stdout": None,
               "stderr": INVALID_INPUT}
        if command is None or command == '':
            return ret
        try:
            stdin, stdout, stderr = self.ssh.exec_command(command, timeout=self.timeout)
            if stdout is not None:
                status_check = stdout.channel.recv_exit_status()
                if status_check == 0:
                    ret["status"] = SUCCESS
                ret["stdout"] = stdout.readlines()
                if stderr is not None:
                    ret["stderr"] = stderr.readlines()
        except Exception as e:
            self.logger.debug("Failed to run command: %s" % e)
        finally:
            self.logger.debug("Connection to host %s on port %s is SUCCESSFUL" % (str(self.host), command))
            return ret

    def scp(self, srcFile, destPath):
        transport = Transport((self.host, int(self.port)))
        transport.connect(username=self.user, password=self.passwd)
        sftp = SFTPClient.from_transport(transport)
        try:
            sftp.put(srcFile, destPath)
        except IOError as e:
            raise e

    def __del__(self):
        self.close()

    def close(self):
        if self.ssh is not None:
            self.ssh.close()
            self.ssh = None