Esempio n. 1
0
def run(exsi,user,pwd,interval):
    try:
        si = SmartConnectNoSSL(host=exsi, user=user, pwd=pwd, port=443)
        atexit.register(Disconnect, si)
        content = si.RetrieveContent()
        vchtime = si.CurrentTime()

        perf_dict = {}
        perfList = content.perfManager.perfCounter
        for counter in perfList:
            counter_full = "{}.{}.{}".format(counter.groupInfo.key, counter.nameInfo.key, counter.rollupType)
            perf_dict[counter_full] = counter.key
        
        for datacenter in content.rootFolder.childEntity:
            datacenter_name = datacenter.name.encode("utf8")
            datastores = datacenter.datastore
            for ds in datastores:
                DatastoreInformation(ds,datacenter_name)

            if hasattr(datacenter.hostFolder, 'childEntity'):
                hostFolder = datacenter.hostFolder
                computeResourceList = []
                computeResourceList = getComputeResource(hostFolder,computeResourceList)
                for computeResource in computeResourceList:
                    ComputeResourceInformation(computeResource,datacenter_name,content,perf_dict,vchtime,interval,exsi)

    except vmodl.MethodFault as error:
        print "Caught vmodl fault : " + error.msg
        return False, error.msg
    return True, "ok"
Esempio n. 2
0
def run(host, user, pwd, port):
    try:
        si = SmartConnectNoSSL(host=host, user=user, pwd=pwd, port=port)
        sitime = si.CurrentTime()
        atexit.register(Disconnect, si)
        content = si.RetrieveContent()
    except vmodl.MethodFault as error:
        print("Caught vmodl fault : " + error.msg)
        return False, error.msg
    return content
Esempio n. 3
0
def main():
    args = GetArgs()
    if args.password:
        password = args.password
    else:
        password = getpass.getpass(prompt='Enter password for host %s and '
                                   'user %s: ' % (args.host, args.user))

    si = SmartConnectNoSSL(host=args.host,
                           user=args.user,
                           pwd=password,
                           port=int(args.port))
    if not si:
        print("Could not connect to the specified host using specified "
              "username and password")
        return -1

    atexit.register(Disconnect, si)

    content = si.RetrieveContent()
    vmnames = ListVms(content)
    # Get vCenter date and time for use as baseline when querying for counters
    vchtime = si.CurrentTime()
    # Get all the performance counters
    perf_dict = {}
    perfList = content.perfManager.perfCounter
    for counter in perfList:
        counter_full = "{}.{}.{}".format(counter.groupInfo.key,
                                         counter.nameInfo.key,
                                         counter.rollupType)
        perf_dict[counter_full] = counter.key

    retProps = GetProperties(content, [vim.VirtualMachine],
                             ['name', 'runtime.powerState'],
                             vim.VirtualMachine)

    #Find VM supplied as arg and use Managed Object Reference (moref) for the PrintVmInfo
    for vm in retProps:
        if (vm['name'] in vmnames) and (vm['runtime.powerState']
                                        == "poweredOn"):
            #PrintVmInfo(vm['moref'], content, vchtime, interval, perf_dict)
            print(
                create_vm_object(vm['name'], vm['moref'], content, vchtime,
                                 interval, perf_dict))
            vm_objects.append(
                create_vm_object(vm['name'], vm['moref'], content, vchtime,
                                 interval, perf_dict))
        elif vm['name'] in vmnames:
            vm_objects.append(
                VM(vm['name'], 999, None, None, None, None, None, None))
            #print('ERROR: Problem connecting to Virtual Machine.  {} is likely powered off or suspended'.format(vm['name']))

    render_html(vm_objects)
    return 0
def run(host, user, pwd, port, interval):
    try:
        si = SmartConnectNoSSL(host=host, user=user, pwd=pwd, port=port)
        atexit.register(Disconnect, si)
        content = si.RetrieveContent()
        vchtime = si.CurrentTime()

        perf_dict = {}
        perfList = content.perfManager.perfCounter
        for counter in perfList:
            counter_full = "{}.{}.{}".format(counter.groupInfo.key,
                                             counter.nameInfo.key,
                                             counter.rollupType)
            perf_dict[counter_full] = counter.key

        for datacenter in content.rootFolder.childEntity:
            datacenter_name = datacenter.name.encode("utf8")
            datastores = datacenter.datastore
            for ds in datastores:
                if (ds.name in config.datastore_names) or (len(
                        config.datastore_names) == 0):
                    DatastoreInformation(ds, datacenter_name)

            if hasattr(datacenter.vmFolder, 'childEntity'):
                hostFolder = datacenter.hostFolder
                computeResourceList = hostFolder.childEntity
                for computeResource in computeResourceList:
                    ComputeResourceInformation(computeResource,
                                               datacenter_name, content,
                                               perf_dict, vchtime, interval)

        if config.vm_enable == True:
            retProps = GetProperties(content, [vim.VirtualMachine],
                                     ['name', 'runtime.powerState'],
                                     vim.VirtualMachine)
            for vm in retProps:
                if (vm["name"] in config.vm_names) or (len(config.vm_names)
                                                       == 0):
                    tags = "vm=" + vm["name"]
                    if vm['runtime.powerState'] == "poweredOn":
                        VmInfo(vm['moref'], content, vchtime, interval,
                               perf_dict, tags)
                        add_data("vm.power", 1, "GAUGE", tags)
                    else:
                        add_data("vm.power", 0, "GAUGE", tags)

    except vmodl.MethodFault as error:
        print "Caught vmodl fault : " + error.msg
        return False, error.msg
    return True, "ok"
Esempio n. 5
0
class Vsphere:
    """ Maintains connection, logging, and constants for a vSphere instance """
    __version__ = "1.0.2"

    def __init__(self,
                 username=None,
                 password=None,
                 hostname=None,
                 datacenter=None,
                 datastore=None,
                 port=443,
                 use_ssl=False):
        """
        Connects to a vCenter server and initializes a class instance.

        :param str username: Username of account to login with
        [default: prompt user]
        :param str password: Password of account to login with
        [default: prompt user]
        :param str hostname: DNS hostname or IP address of vCenter instance
        [default: prompt user]
        :param str datastore: Name of datastore to use
        [default: first datastore found on server]
        :param str datacenter: Name of datacenter to use
        [default: First datacenter found on server]
        :param int port: Port used to connect to vCenter instance
        :param bool use_ssl: If SSL should be used to connect
        :raises LookupError: if a datacenter or datastore cannot be found
        """
        self._log = logging.getLogger('Vsphere')
        self._log.debug(
            "Initializing Vsphere %s\nDatacenter: %s"
            "\tDatastore: %s\tSSL: %s", Vsphere.__version__, datacenter,
            datastore, use_ssl)

        if username is None:
            username = str(input("Enter username for vSphere: "))
        if password is None:
            from getpass import getpass
            password = str(getpass("Enter password for %s: " % username))
        if hostname is None:
            hostname = str(input("Enter hostname for vSphere: "))
        try:
            self._log.info("Connecting to vSphere: %s@%s:%d", username,
                           hostname, port)
            if use_ssl:  # Connect to server using SSL certificate verification
                self._server = SmartConnect(host=hostname,
                                            user=username,
                                            pwd=password,
                                            port=port)
            else:
                self._server = SmartConnectNoSSL(host=hostname,
                                                 user=username,
                                                 pwd=password,
                                                 port=port)
        except vim.fault.InvalidLogin:
            self._log.error("Invalid vSphere login credentials for user %s",
                            username)
            exit(1)
        except Exception as e:
            self._log.exception("Error connecting to vSphere: %s", str(e))
            exit(1)

        # Ensure connection to server is closed on program exit
        from atexit import register
        register(Disconnect, self._server)

        self._log.info("Connected to vSphere host %s:%d", hostname, port)
        self._log.debug("Current server time: %s",
                        str(self._server.CurrentTime()))

        self.username = username
        self.hostname = hostname
        self.port = port
        self.content = self._server.RetrieveContent()
        self.auth = self.content.authorizationManager
        self.user_dir = self.content.userDirectory
        self.search_index = self.content.searchIndex

        self.datacenter = self.get_item(vim.Datacenter, name=datacenter)
        if not self.datacenter:
            raise LookupError(
                "Could not find a Datacenter to initialize with!")
        self.datastore = self.get_datastore(datastore)
        if not self.datastore:
            raise LookupError("Could not find a Datastore to initialize with!")
        self._log.debug("Finished initializing vSphere")

    # From: create_folder_in_datacenter.py in pyvmomi-community-samples
    def create_folder(self, folder_name, create_in=None):
        """
        Creates a VM folder in the specified folder.

        :param str folder_name: Name of folder to create
        :param create_in: Folder to create the new folder in
        [default: root folder of datacenter]
        :type create_in: str or vim.Folder
        :return: The created folder
        :rtype: vim.Folder
        """
        if create_in:
            if isinstance(create_in, str):  # Lookup create_in on the server
                self._log.debug("Retrieving parent folder '%s' from server",
                                create_in)
                parent = self.get_folder(folder_name=create_in)
            else:
                parent = create_in  # Already vim.Folder, so we just assign it
        else:
            parent = self.content.rootFolder  # Default to server root folder
        return parent.create(folder_name)

    def set_motd(self, message):
        """
        Sets vCenter server Message of the Day (MOTD).

        :param str message: Message to set
        """
        self._log.info("Setting vCenter MOTD to %s", message)
        self.content.sessionManager.UpdateServiceMessage(message=str(message))

    def map_items(self,
                  vimtypes,
                  func,
                  name=None,
                  container=None,
                  recursive=True):
        """
        Apply a function to item(s) in a container.

        :param list vimtypes: List of vimtype objects to look for
        :param func: Function to apply
        :param str name: Name of item to apply to
        :param container: Container to search in [default: content.rootFolder]
        :param bool recursive: Whether to recursively descend
        :return: List of values returned from the function call(s)
        :rtype: list
        """
        contain = (self.content.rootFolder if not container else container)
        con_view = self.content.viewManager.CreateContainerView(
            contain, vimtypes, recursive)
        returns = []
        for item in con_view.view:
            if name:
                if hasattr(item, 'name') and item.name.lower() == name.lower():
                    returns.append(func(item))
            else:
                returns.append(func(item))
        con_view.Destroy()
        return returns

    def set_entity_permissions(self, entity, permission):
        """
        Defines or updates rule(s) for the given user or group on the entity.

        :param entity: The entity on which to set permissions
        :type entity: vim.ManagedEntity
        :param permission: The permission to set
        :type permission: vim.AuthorizationManager.Permission
        """
        try:
            self.auth.SetEntityPermissions(entity=entity,
                                           permission=permission)
        except vim.fault.UserNotFound as e:
            self._log.error(
                "Could not find user '%s' to set permission "
                "'%s' on entity '%s'", e.principal, str(permission),
                entity.name)
        except vim.fault.NotFound:
            self._log.error("Invalid role ID for permission '%s'",
                            str(permission))
        except vmodl.fault.ManagedObjectNotFound as e:
            self._log.error("Entity '%s' does not exist to set permission on",
                            str(e.obj))
        except vim.fault.NoPermission as e:
            self._log.error(
                "Could not set permissions for entity '%s': "
                "the current session does not have privilege '%s' "
                "to set permissions for the entity '%s'", entity.name,
                e.privilegeId, e.object)
        except vmodl.fault.InvalidArgument as e:
            self._log.error(
                "Invalid argument to set permission '%s' "
                "on entity '%s': %s", entity.name, str(permission), str(e))
        except Exception as e:
            self._log.exception(
                "Unknown error while setting permissions "
                "for entity '%s': %s", entity.name, str(e))

    def get_entity_permissions(self, entity, inherited=True):
        """
        Gets permissions defined on or effective on a managed entity.

        :param entity: The entity to get permissions for
        :type entity: vim.ManagedEntity
        :param bool inherited: Include propagating permissions
        defined in parent
        :return: The permissions for the entity
        :rtype: vim.AuthorizationManager.Permission or None
        """
        try:
            return self.auth.RetrieveEntityPermissions(entity=entity,
                                                       inherited=inherited)
        except vmodl.fault.ManagedObjectNotFound as e:
            self._log.error(
                "Couldn't find entity '%s' to get permissions from",
                str(e.obj))
            return None

    def get_role_permissions(self, role_id):
        """
        Gets all permissions that use a particular role.

        :param int role_id: ID of the role
        :return: The role permissions
        :rtype: vim.AuthorizationManager.Permission or None
        """
        try:
            return self.auth.RetrieveRolePermissions(roleId=int(role_id))
        except vim.fault.NotFound:
            self._log.error("Role ID %s does not exist", str(role_id))
            return None

    def get_users(self,
                  search='',
                  domain='',
                  exact=False,
                  belong_to_group=None,
                  have_user=None,
                  find_users=True,
                  find_groups=False):
        """
        Returns a list of the users and groups defined for the server

        .. note:: You must hold the Authorization.ModifyPermissions 
        privilege to invoke this method.

        :param str search: Case insensitive substring used to filter results
        [default: all users]
        :param str domain: Domain to be searched [default: local machine]
        :param bool exact: Search should match user/group name exactly
        :param str belong_to_group: Only find users/groups that directly belong
        to this group
        :param str have_user: Only find groups that directly contain this user
        :param bool find_users: Include users in results
        :param bool find_groups: Include groups in results
        :return: The users and groups defined for the server
        :rtype: list(vim.UserSearchResult) or None
        """
        # See for reference: pyvmomi/docs/vim/UserDirectory.rst
        kwargs = {
            "searchStr": search,
            "exactMatch": exact,
            "findUsers": find_users,
            "findGroups": find_groups
        }
        if domain != '':
            kwargs["domain"] = domain
        if belong_to_group is not None:
            kwargs["belongsToGroup"] = belong_to_group
        if have_user is not None:
            kwargs["belongsToUser"] = have_user
        try:
            return self.user_dir.RetrieveUserGroups(**kwargs)
        except vim.fault.NotFound:
            self._log.warning(
                "Could not find domain, group or user "
                "in call to get_users"
                "\nkwargs: %s", str(kwargs))
            return None
        except vmodl.fault.NotSupported:
            self._log.error("System doesn't support domains or "
                            "by-membership queries for get_users")
            return None

    def get_info(self):
        """
        Retrieves and formats basic information about the vSphere instance.

        :return: formatted server information
        :rtype: str
        """
        about = self.content.about
        info_string = "\n"
        info_string += "Host address: %s:%d\n" % (self.hostname, self.port)
        info_string += "Datacenter  : %s\n" % self.datacenter.name
        info_string += "Datastore   : %s\n" % self.datastore.name
        info_string += "Full name   : %s\n" % about.fullName
        info_string += "Vendor      : %s\n" % about.vendor
        info_string += "Version     : %s\n" % about.version
        info_string += "API type    : %s\n" % about.apiType
        info_string += "API version : %s\n" % about.apiVersion
        info_string += "OS type     : %s" % about.osType
        return info_string

    def get_folder(self, folder_name=None):
        """
        Finds and returns the named Folder.

        :param str folder_name: Name of folder [default: Datacenter vmFolder]
        :return: The folder found
        :rtype: vim.Folder
        """
        if folder_name:  # Try to find the named folder in the datacenter
            return self.get_obj(self.datacenter, [vim.Folder], folder_name)
        else:  # Default to the VM folder in the datacenter
            # Reference: pyvmomi/docs/vim/Datacenter.rst
            self._log.warning(
                "Could not find folder '%s' in Datacenter '%s', "
                "defaulting to vmFolder", folder_name, self.datacenter.name)
            return self.datacenter.vmFolder

    def get_vm(self, vm_name):
        """
        Finds and returns the named VM.

        :param str vm_name: Name of the VM
        :return: The VM found
        :rtype: vim.VirtualMachine or None
        """
        return self.get_item(vim.VirtualMachine, vm_name)

    def get_network(self, network_name, distributed=False):
        """
        Finds and returns the named Network.

        :param str network_name: Name or path of the Network
        :param bool distributed: If the Network is a Distributed PortGroup
        :return: The network found
        :rtype: vim.Network or vim.dvs.DistributedVirtualPortgroup or None
        """
        if not distributed:
            return self.get_obj(container=self.datacenter.networkFolder,
                                vimtypes=[vim.Network],
                                name=str(network_name),
                                recursive=True)
        else:
            return self.get_item(vim.dvs.DistributedVirtualPortgroup,
                                 network_name)

    def get_host(self, host_name=None):
        """
        Finds and returns the named Host System.

        :param str host_name: Name of the host
        [default: first host found in datacenter]
        :return: The host found
        :rtype: vim.HostSystem or None
        """
        return self.get_item(vim.HostSystem, host_name)

    def get_cluster(self, cluster_name=None):
        """
        Finds and returns the named Cluster.

        :param str cluster_name: Name of the cluster
        [default: first cluster found in datacenter]
        :return: The cluster found
        :rtype: vim.ClusterComputeResource or None
        """
        return self.get_item(cluster_name, vim.ClusterComputeResource)

    def get_clusters(self):
        """
        Get all the clusters associated with the vCenter server.

        :return: All clusters associated with the vCenter server
        :rtype: list(vim.ClusterComputeResource)
        """
        return self.get_objs(self.content.rootFolder,
                             [vim.ClusterComputeResource])

    def get_datastore(self, datastore_name=None):
        """
        Finds and returns the named Datastore.

        :param str datastore_name: Name of the datastore
        [default: first datastore in datacenter]
        :return: The datastore found
        :rtype: vim.Datastore or None
        """
        return self.datacenter.datastoreFolder.get(datastore_name)

    def get_pool(self, pool_name=None):
        """
        Finds and returns the named vim.ResourcePool.

        :param str pool_name: Name of the resource pool
        [default: first pool found in datacenter]
        :return: The resource pool found
        :rtype: vim.ResourcePool or None
        """
        return self.get_item(vim.ResourcePool, pool_name)

    def get_all_vms(self):
        """
        Finds and returns all VMs registered in the Datacenter.

        :return: All VMs in the Datacenter defined for the class
        :rtype: list(vim.VirtualMachine)
        """
        return self.get_objs(self.datacenter.vmFolder, [vim.VirtualMachine])

    def get_obj(self, container, vimtypes, name, recursive=True):
        """
        Finds and returns named vim object of specified type.

        :param container: Container to search in
        :param list vimtypes: vimtype objects to look for
        :param str name: Name of the object
        :param bool recursive: Recursively search for the item
        :return: Object found with the specified name
        :rtype: vimtype or None
        """
        con_view = self.content.viewManager.CreateContainerView(
            container, vimtypes, recursive)
        obj = None
        for item in con_view.view:
            if item.name.lower() == name.lower():
                obj = item
                break
        con_view.Destroy()
        return obj

    # From: https://github.com/sijis/pyvmomi-examples/vmutils.py
    def get_objs(self, container, vimtypes, recursive=True):
        """
        Get all the vim objects associated with a given type.

        :param container: Container to search in
        :param list vimtypes: Objects to search for
        :param bool recursive: Recursively search for the item
        :return: All vimtype objects found
        :rtype: list(vimtype) or None
        """
        objs = []
        con_view = self.content.viewManager.CreateContainerView(
            container, vimtypes, recursive)
        for item in con_view.view:
            objs.append(item)
        con_view.Destroy()
        return objs

    def get_item(self, vimtype, name=None, container=None, recursive=True):
        """
        Get a item of specified name and type.
        Intended to be simple version of :meth: get_obj

        :param vimtype: Type of item
        :type vimtype: vimtype
        :param str name: Name of item
        :param container: Container to search in
        [default: vCenter server content root folder]
        :param bool recursive: Recursively search for the item
        :return: The item found
        :rtype: vimtype or None
        """
        contain = (self.content.rootFolder if not container else container)
        if not name:
            return self.get_objs(contain, [vimtype], recursive)[0]
        else:
            return self.get_obj(contain, [vimtype], name, recursive)

    def find_by_uuid(self, uuid, instance_uuid=True):
        """
        Find a VM in the datacenter with the given Instance or BIOS UUID.

        :param str uuid: UUID to search for (Instance or BIOS for VMs)
        :param bool instance_uuid: If True, search by VM Instance UUID, 
        otherwise search by BIOS UUID
        :return: The VM found
        :rtype: vim.VirtualMachine or None
        """
        return self.search_index.FindByUuid(datacenter=self.datacenter,
                                            uuid=str(uuid),
                                            vmSearch=True,
                                            instanceUuid=instance_uuid)

    def find_by_ds_path(self, path):
        """
        Finds a VM by it's location on a Datastore.

        :param str path: Path to the VM's .vmx file on the Datastore
        :return: The VM found
        :rtype: vim.VirtualMachine or None
        """
        try:
            return self.search_index.FindByDatastorePath(
                datacenter=self.datacenter, path=str(path))
        except vim.fault.InvalidDatastore:
            self._log.error("Invalid datastore in path: %s", str(path))
            return None

    def find_by_ip(self, ip, vm_search=True):
        """
        Find a VM or Host using a IP address.

        :param str ip: IP address string as returned by VMware Tools ipAddress
        :param vm_search: Search for VMs if True, Hosts if False
        :return: The VM or host found
        :rtype: vim.VirtualMachine or vim.HostSystem or None
        """
        return self.search_index.FindByIp(datacenter=self.datacenter,
                                          ip=str(ip),
                                          vmSearch=vm_search)

    def find_by_hostname(self, hostname, vm_search=True):
        """
        Find a VM or Host using a Fully-Qualified Domain Name (FQDN).

        :param str hostname: FQDN of the VM to find
        :param vm_search: Search for VMs if True, Hosts if False
        :return: The VM or host found
        :rtype: vim.VirtualMachine or vim.HostSystem or None
        """
        return self.search_index.FindByDnsName(datacenter=self.datacenter,
                                               dnsName=hostname,
                                               vmSearch=vm_search)

    def find_by_inv_path(self, path, datacenter=None):
        """
        Finds a vim.ManagedEntity (VM, host, folder, etc) in a inventory.

        :param str path: Path to the entity. This must include the hidden 
        Vsphere folder for the type: vm | network | datastore | host
        Example: "vm/some-things/more-things/vm-name"
        :param str datacenter: Name of datacenter to search in
        [default: instance's datacenter]
        :return: The entity found
        :rtype: vim.ManagedEntity or None
        """
        if datacenter is None:
            datacenter = self.datacenter.name
        full_path = datacenter + "/" + str(path)
        return self.search_index.FindByInventoryPath(inventoryPath=full_path)

    def __repr__(self):
        return "vSphere(%s, %s, %s:%s)" % (self.datacenter.name,
                                           self.datastore.name, self.hostname,
                                           self.port)

    def __str__(self):
        return str(self.get_info())

    def __hash__(self):
        return hash((self.hostname, self.port, self.username))

    def __eq__(self, other):
        return isinstance(other, self.__class__) \
               and self.hostname == other.hostname \
               and self.port == other.port \
               and self.username == other.username

    def __ne__(self, other):
        return not self.__eq__(other)
Esempio n. 6
0
def main():
    args = GetArgs()
    try:
        vmnames = args.vm
        si = None
        if args.password:
            password = args.password
        else:
            password = getpass.getpass(
                prompt="Enter password for host {} and user {}: ".format(
                    args.host, args.user))
        try:
            if args.skip_ssl_validation:
                si = SmartConnectNoSSL(host=args.host,
                                       user=args.user,
                                       pwd=password,
                                       port=int(args.port))
            else:
                si = SmartConnect(host=args.host,
                                  user=args.user,
                                  pwd=password,
                                  port=int(args.port))
        except IOError as e:
            pass
        if not si:
            print(
                f'Could not connect to {args.host} using specified username and password... skip ssl validation?'
            )
            return -1

        atexit.register(Disconnect, si)
        content = si.RetrieveContent()
        # Get vCenter date and time for use as baseline when querying for counters

        # Get all the performance counters
        perf_dict = getPerfDict(content)

        retProps = GetProperties(content, [vim.VirtualMachine],
                                 ['name', 'runtime.powerState'],
                                 vim.VirtualMachine)

        query = None
        if args.format == 'table':
            query = PrintVmInfo
        elif args.format == 'csv':
            query = CsvVmInfo
        else:
            print(f'ERROR: --format {args.format} is not recognized')
            exit(1)

        while True:
            vchtime = si.CurrentTime()
            for vm in retProps:
                if (vm['name'] in vmnames) and (vm['runtime.powerState']
                                                == "poweredOn"):
                    query(vm['moref'], content, vchtime, args.interval,
                          perf_dict)
                elif vm['name'] in vmnames:
                    print(
                        'ERROR: Problem connecting to Virtual Machine.  {} is likely powered off or suspended'
                        .format(vm['name']))
            if args.repeat < 1:
                break
            time.sleep(args.repeat)

    except Exception as e:
        print('Caught exception : ' + str(e))
        return -1

    return 0
class Hello_Esxi():
    def __init__(self, vchost, username, password, port=443):
        self._vcenter_status = {"datastore": [], "esxi": [], "vm": []}
        self._vchost = vchost
        self._username = username
        self._password = password
        self._port = port
        self._payload = []
        self._interval = 60
        self._data = {"datastore": {}, "esxi": {}, "vm": {}}
        self.success, self.msg = self.hello_vcenter()

    def start(self, hass):

        if self.success == True:
            self.run(dt_util.now())
            # 每隔TIME_BETWEEN_UPDATES,调用一次run(),
            track_time_interval(hass, self.run, TIME_BETWEEN_UPDATES)
        else:
            _LOGGER.error(self.msg)

    def set_datastore_names(self, value):
        self._datastore_names = value

    def set_esxi_names(self, value):
        self._esxi_names = value

    def set_vm_names(self, value):
        self._vm_names = value

    def hello_vcenter(self):
        try:
            self.si = SmartConnectNoSSL(host=self._vchost,
                                        user=self._username,
                                        pwd=self._password,
                                        port=self._port)
            hello_content = self.si.RetrieveContent()
            for datacenter in hello_content.rootFolder.childEntity:
                for ds in datacenter.datastore:
                    self._vcenter_status['datastore'].append(ds.name)
                if hasattr(datacenter.hostFolder, 'childEntity'):
                    hostFolder = datacenter.hostFolder
                    computeResourceList = []
                    computeResourceList = self._getComputeResource(
                        hostFolder, computeResourceList)
                    for computeResource in computeResourceList:
                        for host in computeResource.host:
                            self._vcenter_status['esxi'].append(host.name)
            obj = hello_content.viewManager.CreateContainerView(
                hello_content.rootFolder, [vim.VirtualMachine], True)
            for vm in obj.view:
                self._vcenter_status['vm'].append(vm.name)
            return True, json.dumps(self._vcenter_status, indent=4)
        except vmodl.MethodFault as error:
            return False, error.msg
        except Exception as e:
            return False, str(e)

    @property
    def vcenter_status(self):
        return self.success, self.msg

    @property
    def vcenter_info(self):
        return json.dumps(self._data, indent=4)

    def _add_data(self, Resource, name, value):
        # data = {"endpoint":'S_Vcenter',"metric":metric,"timestamp":self.ts,"step":self._interval,"value":value,"counterType":conterType,"tags":tags}
        self._data[Resource][name] = value
        self._payload.append(self._data)

    def _DatastoreInformation(self, datastore, datacenter_name):
        try:
            summary = datastore.summary
            name = summary.name
            TYPE = summary.type

            tags = {
                "datacenter": datacenter_name,
                "datastore": name,
                "type": TYPE
            }

            capacity = summary.capacity
            # self._add_data("datastore_capacity",capacity,"GAUGE",tags)

            freeSpace = summary.freeSpace
            # self._add_data("datastore_free",freeSpace,"GAUGE",tags)

            freeSpacePercentage = (float(freeSpace) / capacity) * 100
            # self._add_data("datastore_freePercent",freeSpacePercentage,"GAUGE",tags)
            value = {
                "datastore_capacity": capacity,
                "datastore_free": freeSpace,
                "datastore_freePercent": freeSpacePercentage
            }
            self._add_data("datastore", name, value)

        except Exception as error:
            _LOGGER.error("Unable to access summary for datastore: ",
                          datastore.name)
            _LOGGER.error(error)
            pass

    def _getComputeResource(self, Folder, computeResourceList):
        if hasattr(Folder, 'childEntity'):
            for computeResource in Folder.childEntity:
                self._getComputeResource(computeResource, computeResourceList)
        else:
            computeResourceList.append(Folder)
        return computeResourceList

    def _ComputeResourceInformation(self, computeResource, datacenter_name,
                                    content, perf_dict, vchtime, interval):
        try:
            hostList = computeResource.host
            computeResource_name = computeResource.name
            for host in hostList:
                if (host.name in self._esxi_names) or (len(self._esxi_names)
                                                       == 0):
                    self._HostInformation(host, datacenter_name,
                                          computeResource_name, content,
                                          perf_dict, vchtime, interval)
        except Exception as error:
            _LOGGER.error(
                "Unable to access information for compute resource: ",
                computeResource.name)
            _LOGGER.error(error)
            pass

    def _HostInformation(self, host, datacenter_name, computeResource_name,
                         content, perf_dict, vchtime, interval):
        try:
            statInt = interval / 20
            summary = host.summary
            stats = summary.quickStats
            hardware = host.hardware

            tags = "datacenter=" + datacenter_name + ",cluster_name=" + computeResource_name + ",host=" + host.name

            uptime = stats.uptime

            cpuUsage = 100 * 1000 * 1000 * float(
                stats.overallCpuUsage) / float(
                    hardware.cpuInfo.numCpuCores * hardware.cpuInfo.hz)

            memoryCapacity = hardware.memorySize

            memoryUsage = stats.overallMemoryUsage * 1024 * 1024

            freeMemoryPercentage = 100 - (
                (float(memoryUsage) / memoryCapacity) * 100)

            statNetworkTx = self._BuildQuery(content, vchtime, (self._perf_id(
                perf_dict, 'net.transmitted.average')), "", host, interval)
            networkTx = (
                float(sum(statNetworkTx[0].value[0].value) * 8 * 1024) /
                statInt)

            statNetworkRx = self._BuildQuery(content, vchtime, (self._perf_id(
                perf_dict, 'net.received.average')), "", host, interval)
            networkRx = (
                float(sum(statNetworkRx[0].value[0].value) * 8 * 1024) /
                statInt)

            value = {
                "esxi_uptime": uptime,
                "esxi_cpu_usage": cpuUsage,
                "esxi_memory_capacity": memoryCapacity,
                "esxi_memory_usage": memoryUsage,
                "esxi_memory_freePercent": freeMemoryPercentage,
                "esxi_net_if_out": networkTx,
                "esxi_net_if_in": networkRx
            }
            self._add_data("esxi", host.name, value)
        except Exception as error:
            _LOGGER.error("Unable to access information for host: ", host.name)
            _LOGGER.error(error)
            pass

    def _BuildQuery(self, content, vchtime, counterId, instance, entity,
                    interval):
        perfManager = content.perfManager
        metricId = vim.PerformanceManager.MetricId(counterId=counterId,
                                                   instance=instance)
        startTime = vchtime - timedelta(seconds=(interval + 60))
        endTime = vchtime - timedelta(seconds=60)
        query = vim.PerformanceManager.QuerySpec(intervalId=20,
                                                 entity=entity,
                                                 metricId=[metricId],
                                                 startTime=startTime,
                                                 endTime=endTime)
        perfResults = perfManager.QueryPerf(querySpec=[query])

        if perfResults:
            return perfResults
        else:
            return False

    def _perf_id(self, perf_dict, counter_name):
        counter_key = perf_dict[counter_name]
        return counter_key

    def _VmInfo(self, vm, content, vchtime, interval, perf_dict, tags):
        try:

            statInt = interval / 20
            summary = vm.summary
            stats = summary.quickStats

            uptime = stats.uptimeSeconds

            cpuUsage = 100 * float(stats.overallCpuUsage) / float(
                summary.runtime.maxCpuUsage)

            memoryUsage = stats.guestMemoryUsage * 1024 * 1024

            memoryCapacity = summary.runtime.maxMemoryUsage * 1024 * 1024

            freeMemoryPercentage = 100 - (
                (float(memoryUsage) / memoryCapacity) * 100)
            statDatastoreRead = self._BuildQuery(
                content, vchtime,
                (self._perf_id(perf_dict, 'datastore.read.average')), "*", vm,
                interval)
            if statDatastoreRead != False:
                DatastoreRead = (
                    float(sum(statDatastoreRead[0].value[0].value) * 1024) /
                    statInt)
            else:
                DatastoreRead = 0

            statDatastoreWrite = self._BuildQuery(
                content, vchtime,
                (self._perf_id(perf_dict, 'datastore.write.average')), "*", vm,
                interval)
            if statDatastoreWrite != False:
                DatastoreWrite = (
                    float(sum(statDatastoreWrite[0].value[0].value) * 1024) /
                    statInt)
            else:
                DatastoreWrite = 0

            statDatastoreIoRead = self._BuildQuery(
                content, vchtime, (self._perf_id(
                    perf_dict, 'datastore.numberReadAveraged.average')), "*",
                vm, interval)
            if statDatastoreIoRead != False:
                DatastoreIoRead = (
                    float(sum(statDatastoreIoRead[0].value[0].value)) /
                    statInt)
            else:
                DatastoreIoRead = 0
            statDatastoreIoWrite = self._BuildQuery(
                content, vchtime, (self._perf_id(
                    perf_dict, 'datastore.numberWriteAveraged.average')), "*",
                vm, interval)
            if statDatastoreIoWrite != False:
                DatastoreIoWrite = (
                    float(sum(statDatastoreIoWrite[0].value[0].value)) /
                    statInt)
            else:
                DatastoreIoWrite = 0
            statDatastoreLatRead = self._BuildQuery(
                content, vchtime, (self._perf_id(
                    perf_dict, 'datastore.totalReadLatency.average')), "*", vm,
                interval)
            if statDatastoreLatRead != False:
                DatastoreLatRead = (
                    float(sum(statDatastoreLatRead[0].value[0].value)) /
                    statInt)
            else:
                DatastoreLatRead = 0
            statDatastoreLatWrite = self._BuildQuery(
                content, vchtime, (self._perf_id(
                    perf_dict, 'datastore.totalWriteLatency.average')), "*",
                vm, interval)
            if statDatastoreLatWrite != False:
                DatastoreLatWrite = (
                    float(sum(statDatastoreLatWrite[0].value[0].value)) /
                    statInt)
            else:
                DatastoreLatWrite = 0
            statNetworkTx = self._BuildQuery(content, vchtime, (self._perf_id(
                perf_dict, 'net.transmitted.average')), "", vm, interval)
            if statNetworkTx != False:
                networkTx = (
                    float(sum(statNetworkTx[0].value[0].value) * 8 * 1024) /
                    statInt)
            else:
                networkTx = 0
            statNetworkRx = self._BuildQuery(content, vchtime, (self._perf_id(
                perf_dict, 'net.received.average')), "", vm, interval)
            if statNetworkRx != False:
                networkRx = (
                    float(sum(statNetworkRx[0].value[0].value) * 8 * 1024) /
                    statInt)
            else:
                networkRx = 0
            value = {
                "powerState": vm.runtime.powerState,
                "vm_uptime": uptime,
                "vm_cpu_usage": cpuUsage,
                "vm_memory_capacity": memoryCapacity,
                "vm_memory_usage": memoryUsage,
                "vm_memory_freePercent": freeMemoryPercentage,
                "vm_net_if_out": networkTx,
                "vm_net_if_in": networkRx,
                "vm_datastore_io_read_bytes": DatastoreRead,
                "vm_datastore_io_write_bytes": DatastoreWrite,
                "vm_datastore_io_read_numbers": DatastoreIoRead,
                "vm_datastore_io_write_numbers": DatastoreIoWrite,
                "vm_datastore_io_read_latency": DatastoreLatRead,
                "vm_datastore_io_write_latency": DatastoreLatWrite
            }
            self._add_data("vm", vm.name, value)
        except Exception as error:
            _LOGGER.error("Unable to access information for host: ", vm.name)
            _LOGGER.error(error)
            pass

    def run(self, now):
        self.ts = int(time.time())

        try:
            content = self.si.RetrieveContent()
            vchtime = self.si.CurrentTime()

            perf_dict = {}
            perfList = content.perfManager.perfCounter
            for counter in perfList:
                counter_full = "{}.{}.{}".format(counter.groupInfo.key,
                                                 counter.nameInfo.key,
                                                 counter.rollupType)
                perf_dict[counter_full] = counter.key
            for datacenter in content.rootFolder.childEntity:
                datacenter_name = datacenter.name
                datastores = datacenter.datastore
                for ds in datastores:
                    if (ds.name in self._datastore_names) or (len(
                            self._datastore_names) == 0):
                        self._DatastoreInformation(ds, datacenter_name)

                if hasattr(datacenter.hostFolder, 'childEntity'):
                    hostFolder = datacenter.hostFolder
                    computeResourceList = []
                    computeResourceList = self._getComputeResource(
                        hostFolder, computeResourceList)
                    for computeResource in computeResourceList:
                        self._ComputeResourceInformation(
                            computeResource, datacenter_name, content,
                            perf_dict, vchtime, self._interval)

            obj = content.viewManager.CreateContainerView(
                content.rootFolder, [vim.VirtualMachine], True)
            for vm in obj.view:
                if (vm.name in self._vm_names) or (len(self._vm_names) == 0):
                    tags = "vm=" + vm.name
                    if vm.runtime.powerState == "poweredOn":
                        self._VmInfo(vm, content, vchtime, self._interval,
                                     perf_dict, tags)
                    else:
                        value = {"powerState": vm.runtime.powerState}
                        self._add_data("vm", vm.name, value)

        except vmodl.MethodFault as error:
            _LOGGER.error("Connect Vcenter Error : " + error.msg)
            return False, error.msg
        return True, "ok"