mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	* refactor: remove trailing whitespace from Python files * Add the GitHub Super-Linter Add Python flake8 linting for W291 trailing whitespace * Add licenses
		
			
				
	
	
		
			288 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python3
 | 
						|
# 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.
 | 
						|
 | 
						|
from pyVim.connect import SmartConnect, SmartConnectNoSSL, Disconnect
 | 
						|
from pyVmomi import vim
 | 
						|
import atexit
 | 
						|
import sys
 | 
						|
import argparse
 | 
						|
import json
 | 
						|
 | 
						|
isDebugLogs = False
 | 
						|
hostClusterNameDict = {}
 | 
						|
pgHostNameDict = {}
 | 
						|
networksDict = {}
 | 
						|
 | 
						|
def log_message(msg):
 | 
						|
    if isDebugLogs == True:
 | 
						|
        print(msg)
 | 
						|
 | 
						|
def get_clusters(content, cluster=None):
 | 
						|
    if cluster is not None:
 | 
						|
        log_message("Getting clusters (name=" + cluster + ") ...")
 | 
						|
    else:
 | 
						|
        log_message("Getting clusters ...")
 | 
						|
    cluster_view = content.viewManager.CreateContainerView(content.rootFolder,
 | 
						|
                                                        [vim.ClusterComputeResource],
 | 
						|
                                                        True)
 | 
						|
    clusters = []
 | 
						|
    if cluster is not None:
 | 
						|
        for c in cluster_view.view:
 | 
						|
            if c.name == cluster:
 | 
						|
                clusters.append(c)
 | 
						|
                hosts = c.host
 | 
						|
                for host in hosts:
 | 
						|
                    hostClusterNameDict[host.name] = c.name
 | 
						|
                break
 | 
						|
    else:
 | 
						|
        for c in cluster_view.view:
 | 
						|
            clusters.append(c)
 | 
						|
            hosts = c.host
 | 
						|
            for host in hosts:
 | 
						|
                hostClusterNameDict[host.name] = c.name
 | 
						|
    cluster_view.Destroy()
 | 
						|
    log_message('\t{} cluster(s) found'.format(len(clusters)))
 | 
						|
    for c in clusters:
 | 
						|
        log_message('\t' + c.name)
 | 
						|
    return clusters
 | 
						|
 | 
						|
 | 
						|
def get_vm_hosts(clusters):
 | 
						|
    log_message("Getting ESX hosts ...")
 | 
						|
    hosts = []
 | 
						|
    for cluster in clusters:
 | 
						|
        hosts.extend(cluster.host)
 | 
						|
    log_message('\t{} host(s) found'.format(len(hosts)))
 | 
						|
    for host in hosts:
 | 
						|
        log_message('\t' + host.name)
 | 
						|
    return hosts
 | 
						|
 | 
						|
 | 
						|
def get_vms(content):
 | 
						|
    log_message("Getting VMs ...")
 | 
						|
    vm_view = content.viewManager.CreateContainerView(content.rootFolder,
 | 
						|
                                                      [vim.VirtualMachine],
 | 
						|
                                                      True)
 | 
						|
    obj = [vm for vm in vm_view.view]
 | 
						|
    vm_view.Destroy()
 | 
						|
    return obj
 | 
						|
 | 
						|
 | 
						|
def get_hosts_port_groups(hosts):
 | 
						|
    log_message("Collecting portGroups on hosts. This may take a while ...")
 | 
						|
    hostPgDict = {}
 | 
						|
    for host in hosts:
 | 
						|
        pgs = host.config.network.portgroup
 | 
						|
        hostPgDict[host] = pgs
 | 
						|
        for pg in pgs:
 | 
						|
            pgHostNameDict[pg.spec.name] = host.name
 | 
						|
        log_message("\tHost {} done.".format(host.name))
 | 
						|
    log_message("\tPortgroup collection complete.")
 | 
						|
    return hostPgDict
 | 
						|
 | 
						|
 | 
						|
def get_vm_info(vm, hostPgDict):
 | 
						|
    vmPowerState = vm.runtime.powerState
 | 
						|
    log_message('\tVM: ' + vm.name + '(' + vmPowerState + ')')
 | 
						|
    get_vm_nics(vm, hostPgDict)
 | 
						|
 | 
						|
 | 
						|
def get_vm_nics(vm, hostPgDict):
 | 
						|
    try:
 | 
						|
        for dev in vm.config.hardware.device:
 | 
						|
            if isinstance(dev, vim.vm.device.VirtualEthernetCard):
 | 
						|
                dev_backing = dev.backing
 | 
						|
                portGroup = None
 | 
						|
                vlanId = None
 | 
						|
                isolatedPvlan = None
 | 
						|
                isolatedPvlanType = None
 | 
						|
                vSwitch = None
 | 
						|
                if hasattr(dev_backing, 'port'):
 | 
						|
                    portGroupKey = dev.backing.port.portgroupKey
 | 
						|
                    dvsUuid = dev.backing.port.switchUuid
 | 
						|
                    try:
 | 
						|
                        dvs = content.dvSwitchManager.QueryDvsByUuid(dvsUuid)
 | 
						|
                    except:
 | 
						|
                        log_message('\tError: Unable retrieve details for distributed vSwitch ' + dvsUuid)
 | 
						|
                        portGroup = ''
 | 
						|
                        vlanId = ''
 | 
						|
                        vSwitch = ''
 | 
						|
                    else:
 | 
						|
                        pgObj = dvs.LookupDvPortGroup(portGroupKey)
 | 
						|
                        portGroup = pgObj.config.name
 | 
						|
                        try:
 | 
						|
                            if isinstance(pgObj.config.defaultPortConfig.vlan, vim.dvs.VmwareDistributedVirtualSwitch.PvlanSpec):
 | 
						|
                                for pvlanConfig in dvs.config.pvlanConfig:
 | 
						|
                                    if pvlanConfig.secondaryVlanId == pgObj.config.defaultPortConfig.vlan.pvlanId:
 | 
						|
                                        vlanId = str(pvlanConfig.primaryVlanId)
 | 
						|
                                        isolatedPvlanType = pvlanConfig.pvlanType
 | 
						|
                                        isolatedPvlan = str(pgObj.config.defaultPortConfig.vlan.pvlanId)
 | 
						|
                                        break
 | 
						|
                            else:
 | 
						|
                                vlanId = str(pgObj.config.defaultPortConfig.vlan.vlanId)
 | 
						|
                        except AttributeError:
 | 
						|
                            log_message('\tError: Unable retrieve details for portgroup ' + portGroup)
 | 
						|
                            vlanId = ''
 | 
						|
                        vSwitch = str(dvs.name)
 | 
						|
                else:
 | 
						|
                    portGroup = dev.backing.network.name
 | 
						|
                    vmHost = vm.runtime.host
 | 
						|
                    # global variable hostPgDict stores portGroups per host
 | 
						|
                    pgs = hostPgDict[vmHost]
 | 
						|
                    for p in pgs:
 | 
						|
                        if portGroup in p.key:
 | 
						|
                            vlanId = str(p.spec.vlanId)
 | 
						|
                            vSwitch = str(p.spec.vswitchName)
 | 
						|
                if portGroup is None:
 | 
						|
                    portGroup = ''
 | 
						|
                if vlanId is None:
 | 
						|
                    vlanId = ''
 | 
						|
                vmHostName = None
 | 
						|
                vmClusterName = None
 | 
						|
                try:
 | 
						|
                    vmHostName = vm.runtime.host.name
 | 
						|
                except AttributeError:
 | 
						|
                    vmHostName = ''
 | 
						|
                try:
 | 
						|
                    vmClusterName = vm.runtime.host.parent.name
 | 
						|
                except AttributeError:
 | 
						|
                    vmClusterName = ''
 | 
						|
                add_network(portGroup, vlanId, isolatedPvlanType, isolatedPvlan, vSwitch, vm.name, dev.deviceInfo.label, dev.macAddress, vmClusterName, vmHostName)
 | 
						|
                log_message('\t\t' + dev.deviceInfo.label + '->' + dev.macAddress +
 | 
						|
                      ' @ ' + vSwitch + '->' + portGroup +
 | 
						|
                      ' (VLAN ' + vlanId + ')')
 | 
						|
    except AttributeError:
 | 
						|
        log_message('\tError: Unable retrieve details for ' + vm.name)
 | 
						|
 | 
						|
def add_network(portGroup, vlanId, isolatedPvlanType, isolatedPvlan, vSwitch, vmName, vmDeviceLabel, vmMacAddress, vmClusterName, vmHostName):
 | 
						|
    key = vSwitch + '->' + portGroup + ' (VLAN ' + vlanId + ')'
 | 
						|
    device = {"label": vmDeviceLabel, "macaddress": vmMacAddress}
 | 
						|
    vm = {"name":vmName, "device": device}
 | 
						|
    if key in networksDict:
 | 
						|
        network = networksDict[key]
 | 
						|
        network["virtualmachines"].append(vm)
 | 
						|
        networksDict[key] = network
 | 
						|
    else:
 | 
						|
        vms = [vm]
 | 
						|
        try:
 | 
						|
            host = pgHostNameDict[portGroup]
 | 
						|
        except KeyError:
 | 
						|
            host = vmHostName
 | 
						|
        try:
 | 
						|
            cluster = hostClusterNameDict[host]
 | 
						|
        except KeyError:
 | 
						|
            cluster = vmClusterName
 | 
						|
 | 
						|
        network = {"portgroup": portGroup, "cluster": cluster, "host": host, "switch": vSwitch, "virtualmachines": vms}
 | 
						|
        if vlanId != '':
 | 
						|
            network["vlanid"] = vlanId
 | 
						|
        if isolatedPvlan is not None:
 | 
						|
            network["isolatedpvlan"] = isolatedPvlan
 | 
						|
        if isolatedPvlanType is not None:
 | 
						|
            network["isolatedpvlantype"] = isolatedPvlanType
 | 
						|
        networksDict[key] = network
 | 
						|
 | 
						|
 | 
						|
def get_args():
 | 
						|
    parser = argparse.ArgumentParser(
 | 
						|
        description='Arguments for talking to vCenter')
 | 
						|
 | 
						|
    parser.add_argument('-s', '--host',
 | 
						|
                        required=True,
 | 
						|
                        action='store',
 | 
						|
                        help='vSpehre service to connect to')
 | 
						|
 | 
						|
    parser.add_argument('-o', '--port',
 | 
						|
                        type=int,
 | 
						|
                        default=443,
 | 
						|
                        action='store',
 | 
						|
                        help='Port to connect on')
 | 
						|
 | 
						|
    parser.add_argument('-u', '--user',
 | 
						|
                        required=True,
 | 
						|
                        action='store',
 | 
						|
                        help='User name to use')
 | 
						|
 | 
						|
    parser.add_argument('-p', '--password',
 | 
						|
                        required=False,
 | 
						|
                        action='store',
 | 
						|
                        help='Password to use')
 | 
						|
 | 
						|
    parser.add_argument('-c', '--cluster',
 | 
						|
                        required=False,
 | 
						|
                        action='store',
 | 
						|
                        help='Cluster for which discover networks')
 | 
						|
 | 
						|
    parser.add_argument('-S', '--disable_ssl_verification',
 | 
						|
                        required=False,
 | 
						|
                        action='store_true',
 | 
						|
                        help='Disable ssl host certificate verification')
 | 
						|
 | 
						|
    parser.add_argument('-d', '--debug',
 | 
						|
                        required=False,
 | 
						|
                        action='store_true',
 | 
						|
                        help='Debug log messages')
 | 
						|
 | 
						|
    args = parser.parse_args()
 | 
						|
    return args
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    global content, isDebugLogs, hostClusterNameDict, pgHostNameDict, networksDict
 | 
						|
    args = get_args()
 | 
						|
    if args.password:
 | 
						|
        password = args.password
 | 
						|
    else:
 | 
						|
        password = getpass.getpass(prompt='Enter password for host %s and '
 | 
						|
                                   'user %s: ' % (args.host, args.user))
 | 
						|
    if args.debug:
 | 
						|
        isDebugLogs = True
 | 
						|
    if args.disable_ssl_verification:
 | 
						|
        serviceInstance = SmartConnectNoSSL(host=args.host,
 | 
						|
                               user=args.user,
 | 
						|
                               pwd=password,
 | 
						|
                               port=int(args.port))
 | 
						|
    else:
 | 
						|
        serviceInstance = SmartConnect(host=args.host,
 | 
						|
                          user=args.user,
 | 
						|
                          pwd=password,
 | 
						|
                          port=int(args.port))
 | 
						|
 | 
						|
    atexit.register(Disconnect, serviceInstance)
 | 
						|
    content = serviceInstance.RetrieveContent()
 | 
						|
    if args.cluster:
 | 
						|
        clusters = get_clusters(content, args.cluster)
 | 
						|
    else:
 | 
						|
        clusters = get_clusters(content)
 | 
						|
    hosts = []
 | 
						|
    if len(clusters) > 0:
 | 
						|
        hosts = get_vm_hosts(clusters)
 | 
						|
    if len(hosts) > 0:
 | 
						|
        hostPgDict = get_hosts_port_groups(hosts)
 | 
						|
        vms = get_vms(content)
 | 
						|
        log_message('\t{} VM(s) found'.format(len(vms)))
 | 
						|
        for vm in vms:
 | 
						|
            get_vm_info(vm, hostPgDict)
 | 
						|
    networks = list(networksDict.values())
 | 
						|
    response = {"count": len(networks), "networks": networks}
 | 
						|
    print(json.dumps(response, indent=2, sort_keys=True))
 | 
						|
 | 
						|
# Main section
 | 
						|
if __name__ == "__main__":
 | 
						|
    sys.exit(main())
 |