diff --git a/lib/vapi-client-bindings/index.html b/lib/vapi-client-bindings/index.html index 19d343d5..431b1e73 100644 --- a/lib/vapi-client-bindings/index.html +++ b/lib/vapi-client-bindings/index.html @@ -1 +1 @@ -vapi_client_bindings-3.1.0-py2.py3-none-any.whl
\ No newline at end of file +vapi_client_bindings-3.2.0-py2.py3-none-any.whl
diff --git a/lib/vapi-client-bindings/vapi_client_bindings-3.1.0-py2.py3-none-any.whl b/lib/vapi-client-bindings/vapi_client_bindings-3.1.0-py2.py3-none-any.whl deleted file mode 100644 index 67b1d9aa..00000000 Binary files a/lib/vapi-client-bindings/vapi_client_bindings-3.1.0-py2.py3-none-any.whl and /dev/null differ diff --git a/lib/vapi-client-bindings/vapi_client_bindings-3.2.0-py2.py3-none-any.whl b/lib/vapi-client-bindings/vapi_client_bindings-3.2.0-py2.py3-none-any.whl new file mode 100644 index 00000000..caab9bd6 Binary files /dev/null and b/lib/vapi-client-bindings/vapi_client_bindings-3.2.0-py2.py3-none-any.whl differ diff --git a/lib/vapi-common-client/index.html b/lib/vapi-common-client/index.html index b00116a3..12f6a356 100644 --- a/lib/vapi-common-client/index.html +++ b/lib/vapi-common-client/index.html @@ -1 +1 @@ -vapi_common_client-2.12.0-py2.py3-none-any.whl
\ No newline at end of file +vapi_common_client-2.14.0-py2.py3-none-any.whl
\ No newline at end of file diff --git a/lib/vapi-common-client/vapi_common_client-2.12.0-py2.py3-none-any.whl b/lib/vapi-common-client/vapi_common_client-2.12.0-py2.py3-none-any.whl deleted file mode 100644 index 481b9bc6..00000000 Binary files a/lib/vapi-common-client/vapi_common_client-2.12.0-py2.py3-none-any.whl and /dev/null differ diff --git a/lib/vapi-common-client/vapi_common_client-2.14.0-py2.py3-none-any.whl b/lib/vapi-common-client/vapi_common_client-2.14.0-py2.py3-none-any.whl new file mode 100644 index 00000000..70aa898f Binary files /dev/null and b/lib/vapi-common-client/vapi_common_client-2.14.0-py2.py3-none-any.whl differ diff --git a/lib/vapi-runtime/index.html b/lib/vapi-runtime/index.html index e4c93f67..39829507 100644 --- a/lib/vapi-runtime/index.html +++ b/lib/vapi-runtime/index.html @@ -1 +1 @@ -vapi_runtime-2.12.0-py2.py3-none-any.whl
\ No newline at end of file +vapi_runtime-2.14.0-py2.py3-none-any.whl
\ No newline at end of file diff --git a/lib/vapi-runtime/vapi_runtime-2.12.0-py2.py3-none-any.whl b/lib/vapi-runtime/vapi_runtime-2.14.0-py2.py3-none-any.whl similarity index 75% rename from lib/vapi-runtime/vapi_runtime-2.12.0-py2.py3-none-any.whl rename to lib/vapi-runtime/vapi_runtime-2.14.0-py2.py3-none-any.whl index 4568d3ae..bdb11c22 100644 Binary files a/lib/vapi-runtime/vapi_runtime-2.12.0-py2.py3-none-any.whl and b/lib/vapi-runtime/vapi_runtime-2.14.0-py2.py3-none-any.whl differ diff --git a/requirements.txt b/requirements.txt index 238129b9..38d9ea4d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ lxml >= 4.3.0 pyVmomi >= 6.7 suds ; python_version < '3' suds-jurko ; python_version >= '3.0' -vapi-client-bindings == 3.1.0 +vapi-client-bindings == 3.2.0 vmc-client-bindings nsx-python-sdk nsx-policy-python-sdk diff --git a/samples/vmc/helpers/sample_cli.py b/samples/vmc/helpers/sample_cli.py index a2a07f49..900c7672 100644 --- a/samples/vmc/helpers/sample_cli.py +++ b/samples/vmc/helpers/sample_cli.py @@ -35,14 +35,14 @@ optional_args = parser.add_argument_group( 'optional arguments') required_args.add_argument( - '--refresh_token', + '--refresh-token', required=True, help='Refresh token obtained from CSP') required_args.add_argument( - '--org_id', + '--org-id', required=True, help='Orgization ID') required_args.add_argument( - '--sddc_id', + '--sddc-id', required=True, help='SDDC ID') diff --git a/samples/vmc/networks_nsxt/l3_vpn_crud.py b/samples/vmc/networks_nsxt/l3_vpn_crud.py index e1162096..be967761 100644 --- a/samples/vmc/networks_nsxt/l3_vpn_crud.py +++ b/samples/vmc/networks_nsxt/l3_vpn_crud.py @@ -39,7 +39,7 @@ class NSXPolicyL3VPN(object): """ def __init__(self): - required_args.add_argument('--remote_endpoint_public_ip', + required_args.add_argument('--remote-endpoint-public-ip', required=True, help='L3 VPN Remote end point\'s public ip') diff --git a/samples/vmc/networks_nsxt/security_group_create.py b/samples/vmc/networks_nsxt/security_group_create.py index dab65011..728b7aa7 100644 --- a/samples/vmc/networks_nsxt/security_group_create.py +++ b/samples/vmc/networks_nsxt/security_group_create.py @@ -36,7 +36,7 @@ Create a new NSX-T Group on MGW or CGW Sample Prerequisites: - SDDC deployed in VMware Cloud on AWS """ -optional_args.add_argument('--gateway_type', +optional_args.add_argument('--gateway-type', default='mgw', help='Gateway type. Either mgw or cgw') @@ -44,11 +44,11 @@ required_args.add_argument('--name', required=True, help='Name of the security group to be created') -optional_args.add_argument('--ip_address', +optional_args.add_argument('--ip-address', default='172.31.0.0/24', help='IP address for the expression') -optional_args.add_argument('--group_id', +optional_args.add_argument('--group-id', help='ID of the group. A random ID will be used by default') args = parser.parse_args() diff --git a/samples/vmc/networks_nsxt/security_group_delete.py b/samples/vmc/networks_nsxt/security_group_delete.py index 2af72759..45686a8a 100644 --- a/samples/vmc/networks_nsxt/security_group_delete.py +++ b/samples/vmc/networks_nsxt/security_group_delete.py @@ -39,11 +39,11 @@ Sample Prerequisites: - SDDC deployed in VMware Cloud on AWS - A NSX-T security group """ -optional_args.add_argument('--gateway_type', +optional_args.add_argument('--gateway-type', default='mgw', help='Gateway type. Either mgw or cgw') -optional_args.add_argument('--group_id', +optional_args.add_argument('--group-id', help='ID of the group to be deleted') args = parser.parse_args() diff --git a/samples/vmc/networks_nsxt/security_group_update.py b/samples/vmc/networks_nsxt/security_group_update.py index 945fb7f6..180ca983 100644 --- a/samples/vmc/networks_nsxt/security_group_update.py +++ b/samples/vmc/networks_nsxt/security_group_update.py @@ -40,11 +40,11 @@ Sample Prerequisites: - SDDC deployed in VMware Cloud on AWS - A NSX-T security group """ -optional_args.add_argument('--gateway_type', +optional_args.add_argument('--gateway-type', default='mgw', help='Gateway type. Either mgw or cgw') -optional_args.add_argument('--group_id', +optional_args.add_argument('--group-id', help='ID of the group to be updated') required_args.add_argument('--name', diff --git a/samples/vmc/orgs/organization_operations.py b/samples/vmc/orgs/organization_operations.py index 0c7e76a2..912244c8 100644 --- a/samples/vmc/orgs/organization_operations.py +++ b/samples/vmc/orgs/organization_operations.py @@ -41,7 +41,7 @@ class OperationsOnOrganizations(object): required_args = parser.add_argument_group( 'required arguments') required_args.add_argument( - '--refresh_token', + '--refresh-token', required=True, help='VMware Cloud API refresh token') diff --git a/samples/vmc/tasks/cancel_task.py b/samples/vmc/tasks/cancel_task.py index 3f551f9b..df7103d7 100644 --- a/samples/vmc/tasks/cancel_task.py +++ b/samples/vmc/tasks/cancel_task.py @@ -32,7 +32,7 @@ required_args = parser.add_argument_group( 'required arguments') required_args.add_argument( - '--refresh_token', + '--refresh-token', required=True, help='Refresh token obtained from CSP') diff --git a/samples/vmc/tasks/list_tasks.py b/samples/vmc/tasks/list_tasks.py index 6546b4ae..dcb73665 100644 --- a/samples/vmc/tasks/list_tasks.py +++ b/samples/vmc/tasks/list_tasks.py @@ -34,7 +34,7 @@ required_args = parser.add_argument_group( 'required arguments') required_args.add_argument( - '--refresh_token', + '--refresh-token', required=True, help='Refresh token obtained from CSP') required_args.add_argument( diff --git a/samples/vmc/tasks/list_tasks_stg.py b/samples/vmc/tasks/list_tasks_stg.py index ea17d352..9c0c619e 100644 --- a/samples/vmc/tasks/list_tasks_stg.py +++ b/samples/vmc/tasks/list_tasks_stg.py @@ -36,7 +36,7 @@ optional_args = parser.add_argument_group( 'optional arguments') required_args.add_argument( - '--refresh_token', + '--refresh-token', required=True, help='Refresh token obtained from CSP') diff --git a/samples/vsphere/appliances/timezone.py b/samples/vsphere/appliances/timezone.py new file mode 100644 index 00000000..4ee3e00b --- /dev/null +++ b/samples/vsphere/appliances/timezone.py @@ -0,0 +1,51 @@ +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2019. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '6.7+' + +from vmware.vapi.vsphere.client import create_vsphere_client + +from samples.vsphere.common import (sample_cli, sample_util) +from samples.vsphere.common.ssl_helper import get_unverified_session + + +""" +Demonstrates setting and getting TimeZone.Accepted values are + +valid Timezone values for appliance + +""" + +parser = sample_cli.build_arg_parser() + +parser.add_argument( + '--time_sync', + required=True, + action='store', + choices=['DISABLED', 'HOST'], + help='DISABLED,time synchronization is disabled and HOST,Host time synchronization ') + +args = sample_util.process_cli_args(parser.parse_args()) +time_sync = args.time_sync + +# Connect to vAPI services +session = get_unverified_session() if args.skipverification else None +client = create_vsphere_client(server=args.server, + username=args.username, + password=args.password, + session=session) +timesync_mode = client.appliance.Timesync.TimeSyncMode(time_sync) +print("Setting the appliance time syncronization as : " + time_sync) +client.appliance.Timesync.set(timesync_mode) +print("Timesync as : " + client.appliance.Timesync.get()) diff --git a/samples/vsphere/contentlibrary/lib/cls_api_client.py b/samples/vsphere/contentlibrary/lib/cls_api_client.py index c7437a22..6675619c 100644 --- a/samples/vsphere/contentlibrary/lib/cls_api_client.py +++ b/samples/vsphere/contentlibrary/lib/cls_api_client.py @@ -18,6 +18,7 @@ from com.vmware.content_client import (Library, LocalLibrary, SubscribedLibrary) from com.vmware.content.library_client import Item, SubscribedItem, Subscriptions +from com.vmware.content.library.item_client import Changes from com.vmware.content.library.item_client import DownloadSession from com.vmware.content.library.item_client import UpdateSession from com.vmware.content.library.item.downloadsession_client import File as DownloadSessionFile @@ -26,6 +27,7 @@ from com.vmware.vcenter_client import VM from com.vmware.vcenter.iso_client import Image from com.vmware.vcenter.ovf_client import LibraryItem from com.vmware.vcenter.vm_template_client import LibraryItems as VmtxLibraryItem +from com.vmware.vcenter.vm_template.library_items_client import CheckOuts, Versions class ClsApiClient(object): @@ -77,9 +79,23 @@ class ClsApiClient(object): # machine templates self.vmtx_service = VmtxLibraryItem(self.service_manager.stub_config) - # #### + # Returns the service for managing subscription information of + # the subscribers of a published library. self.subscriptions = Subscriptions(self.service_manager.stub_config) # Creates the service that communicates with virtual machines self.vm_service = VM(self.service_manager.stub_config) + + # Returns the service for managing checkouts of a library item containing + # a virtual machine template + self.check_outs_service = CheckOuts(self.service_manager.stub_config) + + # Returns the service for managing the live versions of the virtual machine + # templates contained in a library item + self.versions_service = Versions(self.service_manager.stub_config) + + # Returns the service for managing the history of content changes made + # to a library item + self.changes_service = Changes(self.service_manager.stub_config) + # TODO: Add the other CLS services, eg. storage, config, type diff --git a/samples/vsphere/contentlibrary/vmtemplate/check_out_vm_template_workflow.py b/samples/vsphere/contentlibrary/vmtemplate/check_out_vm_template_workflow.py new file mode 100644 index 00000000..3bb6adc6 --- /dev/null +++ b/samples/vsphere/contentlibrary/vmtemplate/check_out_vm_template_workflow.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python + +""" +* ******************************************************* +* Copyright VMware, Inc. 2019. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '7.0.0+' + +from pyVmomi import vim +from com.vmware.vcenter.vm_template.library_items_client import CheckOuts +from com.vmware.vcenter.vm_template.library_items_client import Versions + +from vmware.vapi.vsphere.client import create_vsphere_client + +from samples.vsphere.common.id_generator import rand +from samples.vsphere.common.sample_base import SampleBase +from samples.vsphere.common.ssl_helper import get_unverified_session +from samples.vsphere.common.vim.helpers.vim_utils import get_obj_by_moId +from samples.vsphere.contentlibrary.lib.cls_api_client import ClsApiClient +from samples.vsphere.contentlibrary.lib.cls_api_helper import ClsApiHelper +from samples.vsphere.vcenter.helper.resource_pool_helper import ( + get_resource_pool) + + +class CheckOutVmTemplateWorkflow(SampleBase): + """ + Demonstrates how to check out a VM from a library item containing a virtual + machine template, check in the VM checked out from the item, and rollback + the item to a previous version. + + Prerequisites: + - A library item containing a virtual machine template + - A resource pool + - A datacenter + """ + + def __init__(self): + SampleBase.__init__(self, self.__doc__) + self.servicemanager = None + self.client = None + self.helper = None + self.item_name = None + self.vm_name = None + self.datacenter_name = None + self.resource_pool_name = None + + def _options(self): + self.argparser.add_argument('-itemname', '--itemname', + required=True, + help='The name of the library item ' + 'containing the VM template ' + 'to be checked out') + self.argparser.add_argument('-datacentername', '--datacentername', + required=True, + help='The name of the datacenter in which ' + 'to check out the VM') + self.argparser.add_argument('-resourcepoolname', '--resourcepoolname', + required=True, + help='The name of the resource pool in ' + 'the datacenter in which to place ' + 'the VM') + self.argparser.add_argument('-vmname', '--vmname', + help='The name of the VM to check out of ' + 'the library item') + + def _setup(self): + # Required arguments + self.datacenter_name = self.args.datacentername + self.resource_pool_name = self.args.resourcepoolname + self.item_name = self.args.itemname + + # Optional arguments + self.vm_name = (self.args.vmname if self.args.vmname + else rand('checked-out-vm-')) + + self.servicemanager = self.get_service_manager() + self.client = ClsApiClient(self.servicemanager) + self.helper = ClsApiHelper(self.client, self.skip_verification) + + session = get_unverified_session() if self.skip_verification else None + self.vsphere_client = create_vsphere_client(server=self.server, + username=self.username, + password=self.password, + session=session) + + def _execute(self): + # Get the identifiers + item_id = self.helper.get_item_id_by_name(self.item_name) + assert item_id + + resource_pool_id = get_resource_pool(self.vsphere_client, + self.datacenter_name, + self.resource_pool_name) + assert resource_pool_id + + version_before_check_out = self.client.library_item_service.get( + item_id).content_version + + self.print_live_versions(item_id) + + # Build the check out spec + check_out_spec = CheckOuts.CheckOutSpec() + placement_spec = CheckOuts.PlacementSpec() + placement_spec.resource_pool = resource_pool_id + check_out_spec.placement = placement_spec + check_out_spec.name = self.vm_name + + # Check out VM from item + vm_id = self.client.check_outs_service.check_out(item_id, + check_out_spec) + print("VM (ID: {}) checked out from item".format(vm_id)) + + # Get library id associated with checked out VM + info = self.vsphere_client.vcenter.vm.LibraryItem.get( + vm_id) + assert info.check_out + print("Library item associated with checked out VM is {}".format( + info.check_out.library_item)) + + # Check in VM into the library item + check_in_spec = CheckOuts.CheckInSpec() + check_in_spec.message = "Check in message" + version_after_check_in = self.client.check_outs_service.check_in( + item_id, vm_id, check_in_spec) + print("VM (ID: {}) checked into item {}".format(vm_id, item_id)) + self.print_live_versions(item_id) + + # Rollback to previous version + rollback_message = "Rollback to v{}".format(version_before_check_out) + rollback_spec = Versions.RollbackSpec(rollback_message) + version_after_rollback = self.client.versions_service.rollback( + item_id, version_before_check_out, rollback_spec) + print("Item rolled back to version {}. New item version is {}".format( + version_before_check_out, version_after_rollback)) + self.print_live_versions(item_id) + + # Delete previous version + self.client.versions_service.delete(item_id, version_after_check_in) + print("Deleted version {} of item".format(version_after_check_in)) + self.print_live_versions(item_id) + self.print_change_history(item_id) + + def print_live_versions(self, item_id): + # Get and print live versions of the VM template item + versions_info = self.client.versions_service.list(item_id) + print("Live versions of VM template item:") + for version_info in versions_info: + vm_template = get_obj_by_moId(self.servicemanager.content, + [vim.VirtualMachine], + version_info.vm_template) + print("Version: {}, VM template name: {}".format( + version_info.version, vm_template.name)) + + def print_change_history(self, item_id): + # Get and print change history of the VM template item + changes_summary = self.client.changes_service.list(item_id) + print("Change history of VM template item:") + for change_summary in changes_summary: + print("Change version: {}, Time: {}, User: {}, Message: {}".format( + change_summary.version, change_summary.time, + change_summary.user, change_summary.short_message)) + + +def main(): + check_out_workflow_sample = CheckOutVmTemplateWorkflow() + check_out_workflow_sample.main() + + +if __name__ == '__main__': + main() diff --git a/samples/vsphere/vcenter/helper/guest_helper.py b/samples/vsphere/vcenter/helper/guest_helper.py new file mode 100644 index 00000000..ca069f15 --- /dev/null +++ b/samples/vsphere/vcenter/helper/guest_helper.py @@ -0,0 +1,91 @@ +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2019. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '6.7+' + +import time +import logging +from com.vmware.vcenter.vm.guest_client import Power +from com.vmware.vcenter.vm.guest_client import Identity +from com.vmware.vapi.std.errors_client import (NotFound, ServiceUnavailable) + + +def wait_for_guest_info_ready(vsphere_client, vmId, timeout): + """ + Waits for the Tools info to be ready, or times out. + """ + print('Waiting for guest info to be ready.') + start = time.time() + timeout = start + timeout + while timeout > time.time(): + logging.info('Waiting for guest info to be ready') + time.sleep(1) + try: + result = vsphere_client.vcenter.vm.guest.Identity.get(vmId) + break + except ServiceUnavailable as e: + logging.debug('Got ServiceUnavailable waiting for guest info') + pass + except Exception as e: + print('Unexpected exception %s waiting for guest info' % e) + raise e + if time.time() >= timeout: + raise Exception('Timed out waiting for guest info to be available.\n' + 'Be sure the VM has VMware Tools.') + else: + logging.info('Took %d seconds for guest info to be available' + % (time.time() - start)) + + +def wait_for_guest_power_state(vsphere_client, vmId, desiredState, timeout): + """ + Waits for the guest to reach the desired power state, or times out. + """ + print("Waiting for guest power state {}".format(desiredState)) + start = time.time() + timeout = start + timeout + while timeout > time.time(): + time.sleep(1) + curState = vsphere_client.vcenter.vm.guest.Power.get(vmId).state + logging.debug('Current guest power state is %s, looking for %s' + % (curState, desiredState)) + if desiredState == curState: + break + if desiredState != curState: + raise Exception('Timed out waiting for guest to reach desired power state') + else: + logging.info('Took %s seconds for guest power state to change to %s' + % (time.time() - start, desiredState)) + + +def wait_for_power_operations_state(vsphere_client, vmId, desiredState, timeout): + """ + Waits for the desired soft power operations state, or times out. + """ + print('Waiting for guest power operations to be {}'.format(desiredState)) + start = time.time() + timeout = start + timeout + while timeout > time.time(): + time.sleep(1) + curState = vsphere_client.vcenter.vm.guest.Power.get(vmId).operations_ready + logging.debug('Current guest operations ready state is %s,' + ' looking for %s' % (curState, desiredState)) + if desiredState == curState: + break + if desiredState != curState: + raise Exception('Timed out waiting for guest to reach desired ' + ' operations ready state') + else: + logging.info('Took %s seconds for guest operations ready state\ + to change to %s' % (time.time() - start, desiredState)) diff --git a/samples/vsphere/vcenter/vm/guest/info.py b/samples/vsphere/vcenter/vm/guest/info.py new file mode 100644 index 00000000..fb892f28 --- /dev/null +++ b/samples/vsphere/vcenter/vm/guest/info.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python + +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2019. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '6.7+' + +import logging + +from com.vmware.vcenter.vm_client import Power as HardPower +from com.vmware.vapi.std.errors_client import (NotFound, ServiceUnavailable) +from com.vmware.vcenter.vm.guest_client import Power +from com.vmware.vcenter.vm.guest_client import Identity +from com.vmware.vcenter.vm.guest_client import LocalFilesystem +from vmware.vapi.vsphere.client import create_vsphere_client +from samples.vsphere.common.sample_util import parse_cli_args_vm +from samples.vsphere.common.sample_util import pp +from samples.vsphere.vcenter.setup import testbed +from samples.vsphere.vcenter.helper.vm_helper import get_vm +from samples.vsphere.common.ssl_helper import get_unverified_session +from samples.vsphere.vcenter.helper.guest_helper import \ + (wait_for_guest_info_ready, wait_for_guest_power_state) + +""" +Demonstrates the virtual machine guest information. + +Sample Prerequisites: +The sample needs an existing VM with VMware Tools. +""" + + +class GuestInfo(object): + """ + Demonstrates guest information APIs + Sample Prerequisites: + vCenter/ESX + """ + def __init__(self): + server, username, password, self.cleardata, \ + skip_verification, self.vm_name = \ + parse_cli_args_vm(testbed.config['VM_NAME_DEFAULT']) + + session = get_unverified_session() if skip_verification else None + self.vsphere_client = create_vsphere_client(server=server, + username=username, + password=password, + session=session) + + # Increase the logging level for more detailed output. + # logging.basicConfig(level=logging.DEBUG) + + def run(self): + # find the given VM + self.vm = get_vm(self.vsphere_client, self.vm_name) + if not self.vm: + raise Exception('Sample requires an existing vm with name ({}).' + 'Please create the vm first.'.format(self.vm_name)) + print("Using VM '{}' ({}) for Guest Info Sample" + .format(self.vm_name, self.vm)) + + # power on the VM if necessary + status = self.vsphere_client.vcenter.vm.Power.get(self.vm) + if status != HardPower.Info(state=HardPower.State.POWERED_ON): + print('Powering on VM.') + self.vsphere_client.vcenter.vm.Power.start(self.vm) + + # wait for guest info to be ready + wait_for_guest_info_ready(self.vsphere_client, self.vm, 600) + + # get the Identity + identity = self.vsphere_client.vcenter.vm.guest.Identity.get(self.vm) + print('vm.guest.Identity.get({})'.format(self.vm)) + print('Identity: {}'.format(pp(identity))) + + # get the local filesystem info + local_filesysteem = \ + self.vsphere_client.vcenter.vm.guest.LocalFilesystem.get(self.vm) + print('vm.guest.LocalFilesystem.get({})'.format(self.vm)) + print('LocalFilesystem: {}'.format(pp(local_filesysteem))) + + def cleanup(self): + # shut down the vm if requested + if self.cleardata: + print('\n# Cleanup: Shutdown the vm') + self.vsphere_client.vcenter.vm.guest.Power.shutdown(self.vm) + print('vm.guest.Power.shutdown({})'.format(self.vm)) + wait_for_guest_power_state(self.vsphere_client, self.vm, + Power.State.NOT_RUNNING, 300) + + +def main(): + info = GuestInfo() + info.run() + info.cleanup() + + +if __name__ == '__main__': + main() diff --git a/samples/vsphere/vcenter/vm/guest/power.py b/samples/vsphere/vcenter/vm/guest/power.py new file mode 100644 index 00000000..6063d393 --- /dev/null +++ b/samples/vsphere/vcenter/vm/guest/power.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2019. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '6.7+' + +import logging + +from com.vmware.vcenter.vm_client import Power as HardPower +from com.vmware.vapi.std.errors_client import (NotFound, ServiceUnavailable) +from com.vmware.vcenter.vm.guest_client import Power +from com.vmware.vcenter.vm.guest_client import Identity +from vmware.vapi.vsphere.client import create_vsphere_client +from samples.vsphere.common.sample_util import parse_cli_args_vm +from samples.vsphere.common.sample_util import pp +from samples.vsphere.vcenter.setup import testbed +from samples.vsphere.vcenter.helper.vm_helper import get_vm +from samples.vsphere.common.ssl_helper import get_unverified_session +from samples.vsphere.vcenter.helper.guest_helper import \ + (wait_for_guest_info_ready, wait_for_guest_power_state, + wait_for_power_operations_state) + +""" +Demonstrates the virtual machine soft power operations. + +Sample Prerequisites: +The sample needs an existing VM with VMware Tools. +""" +STATE_TIMEOUT = 300 + + +class SoftPower(object): + """ + Demonstrates soft power APIs + Sample Prerequisites: + vCenter/ESX + """ + def __init__(self): + server, username, password, self.cleardata, \ + skip_verification, self.vm_name = \ + parse_cli_args_vm(testbed.config['VM_NAME_DEFAULT']) + + session = get_unverified_session() if skip_verification else None + self.vsphere_client = create_vsphere_client(server=server, + username=username, + password=password, + session=session) + + # Increase the logging level for more detailed output. + # logging.basicConfig(level=logging.DEBUG) + + def run(self): + self.vm = get_vm(self.vsphere_client, self.vm_name) + if not self.vm: + raise Exception('Sample requires an existing vm with name ({}).' + 'Please create the vm first.'.format(self.vm_name)) + print("Using VM '{}' ({}) for Guest Power Sample".format(self.vm_name, + self.vm)) + + # power on the VM if necessary + status = self.vsphere_client.vcenter.vm.Power.get(self.vm) + if status != HardPower.Info(state=HardPower.State.POWERED_ON): + print("Powering on VM {}.".format(self.vm_name)) + self.vsphere_client.vcenter.vm.Power.start(self.vm) + print('vm.Power.start({})'.format(self.vm)) + + # reboot the guest + wait_for_power_operations_state(self.vsphere_client, self.vm, + True, STATE_TIMEOUT) + print('\n# Example: Reboot the vm') + identity = self.vsphere_client.vcenter.vm.guest.Power.reboot(self.vm) + wait_for_power_operations_state(self.vsphere_client, self.vm, + False, STATE_TIMEOUT) + print('Tools have stopped.') + wait_for_guest_power_state(self.vsphere_client, self.vm, + Power.State.RUNNING, STATE_TIMEOUT) + wait_for_power_operations_state(self.vsphere_client, self.vm, + True, STATE_TIMEOUT) + print('vm.guest.Power.reboot({})'.format(self.vm)) + + # Standby the guest -- already running from previous step + print('\n# Example: Standby the vm') + self.vsphere_client.vcenter.vm.guest.Power.standby(self.vm) + wait_for_guest_power_state(self.vsphere_client, self.vm, + Power.State.NOT_RUNNING, STATE_TIMEOUT) + print('vm.guest.Power.standby({})'.format(self.vm)) + + # shutdown the guest + # power back on from previous standby + self.vsphere_client.vcenter.vm.Power.start(self.vm) + wait_for_power_operations_state(self.vsphere_client, self.vm, + True, STATE_TIMEOUT) + print("Shutting down VM {}.".format(self.vm_name)) + self.vsphere_client.vcenter.vm.guest.Power.shutdown(self.vm) + wait_for_guest_power_state(self.vsphere_client, self.vm, + Power.State.NOT_RUNNING, STATE_TIMEOUT) + print('vm.guest.Power.shutdown({})'.format(self.vm)) + + def cleanup(self): + # no-op, sample leaves VM off + return + + +def main(): + soft_power = SoftPower() + soft_power.run() + soft_power.cleanup() + + +if __name__ == '__main__': + main() diff --git a/samples/vsphere/vcenter/vstats/README.md b/samples/vsphere/vcenter/vstats/README.md new file mode 100644 index 00000000..2b3f656c --- /dev/null +++ b/samples/vsphere/vcenter/vstats/README.md @@ -0,0 +1,41 @@ +This directory contains samples for managing vSphere Stats platform and querying for stats data: + +### vSphere Stats Discovery APIs - List Counters, List Counter Metadata, Get Resource Address Schema, List Providers, List Resource types, List Metrics, List Counter-sets +Sample | Description +----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------- +discovery.py | Demonstrates all vSphere Stats discovery APIs which give current state of the system. + +### vSphere Stats Acquisition Specification Create/Get/List/Delete/Update operations +Sample | Description +----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------- +acquisitionspec/lifecycle.py | Demonstrates create, get, list, update and delete operations of Acquisition Specifications. + +### vSphere Stats End to End workflow - Create an Acquisition Specification and query for data points +Sample | Description +----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------- +data/query_data_points.py | Demonstrates creation of Acquisition Specification and query for data points filtered by cid. +data/query_data_points_set_id.py | Demonstrates creation of Acquisition Specification using Counter SetId and query for data points filtered by resource. +data/query_data_points_with_predicate.py | Demonstrates creation of Acquisition Specification using QueryPredicate "ALL" and query for data points filtered by cid. + + +To view the available command-line options: + + $ python discovery.py --help + $ python acquisitionspec/lifecycle.py --help + $ python data/query_data_points.py --help + $ python data/query_data_points_set_id.py --help + $ python data/query_data_points_with_predicate.py --help + +Running the samples: + + $ python discovery.py --server --username --password --skipverification + $ python acquisitionspec/lifecycle.py --server --username --password --skipverification --interval --expiration + $ python data/query_data_points.py --server --username --password --skipverification --interval --expiration + $ python data/query_data_points_set_id.py --server --username --password --skipverification --interval --expiration + $ python data/query_data_points_with_predicate.py --server --username --password --skipverification --interval --expiration + + +### Testbed Requirement: + - 1 vCenter Server on version 7.0x or higher + - 2 ESXi hosts on version 7.0x or higher with VMs + - 1 datastore diff --git a/samples/vsphere/vcenter/vstats/__init__.py b/samples/vsphere/vcenter/vstats/__init__.py new file mode 100644 index 00000000..8e16649d --- /dev/null +++ b/samples/vsphere/vcenter/vstats/__init__.py @@ -0,0 +1,25 @@ +""" +* ******************************************************* +* Copyright VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__copyright__ = 'Copyright 2020 VMware, Inc. All rights reserved.' + + +# Required to distribute different parts of this +# package as multiple distribution +try: + import pkg_resources + pkg_resources.declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) # @ReservedAssignment diff --git a/samples/vsphere/vcenter/vstats/acquisitionspec/__init__.py b/samples/vsphere/vcenter/vstats/acquisitionspec/__init__.py new file mode 100644 index 00000000..8e16649d --- /dev/null +++ b/samples/vsphere/vcenter/vstats/acquisitionspec/__init__.py @@ -0,0 +1,25 @@ +""" +* ******************************************************* +* Copyright VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__copyright__ = 'Copyright 2020 VMware, Inc. All rights reserved.' + + +# Required to distribute different parts of this +# package as multiple distribution +try: + import pkg_resources + pkg_resources.declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) # @ReservedAssignment diff --git a/samples/vsphere/vcenter/vstats/acquisitionspec/lifecycle.py b/samples/vsphere/vcenter/vstats/acquisitionspec/lifecycle.py new file mode 100644 index 00000000..67fab8cc --- /dev/null +++ b/samples/vsphere/vcenter/vstats/acquisitionspec/lifecycle.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '7.0+' + +import random + +from com.vmware.vstats_client import Providers, AcqSpecs, CidMid, RsrcId + +from samples.vsphere.common import sample_util +from samples.vsphere.vcenter.hcl.utils import get_configuration +from samples.vsphere.vcenter.vstats.helpers.sample_cli import parser + + +class SampleAcquisitionSpecLifecycle(object): + """ + Demonstrates create, get, list, update and delete operations of + Acquisition Specifications. + Sample Prerequisites: + vCenter 7.0x with 7.0x ESXi hosts. + """ + + def __init__(self): + args = sample_util.process_cli_args(parser.parse_args()) + self.interval = int(args.interval) + self.expiration = int(args.expiration) + + stub_config = get_configuration( + args.server, args.username, args.password, + args.skipverification) + self.providers_client = Providers(stub_config) + self.acq_specs_client = AcqSpecs(stub_config) + + def run(self): + cid = "cpu.capacity.demand.HOST" + new_cid = "mem.capacity.usage.HOST" + host_type = "HOST" + memo = "user definition of acquisition spec" + + # The counter and associated resources can be chosen using discovery + # APIs. Please refer to samples in discovery package to obtain this + # metadata. In this sample, we create an Acquisition + # Specification for a HOST counter. + cid_mid_obj = CidMid(cid=cid) + counter_spec_obj = self.acq_specs_client.CounterSpec( + cid_mid=cid_mid_obj) + + # Choose a random host from which stats data needs to be collected. + providers = self.providers_client.list() + random_host_id = random.choice(providers).id_value + host_resource_id_obj = RsrcId(id_value=random_host_id, + type=host_type) + acq_spec_obj = self.acq_specs_client.CreateSpec( + counters=counter_spec_obj, + resources=[host_resource_id_obj], + interval=self.interval, + expiration=self.expiration, + memo_=memo + ) + + # Create an Acquisition Specification. + acq_spec_id = self.acq_specs_client.create(acq_spec_obj) + SampleAcquisitionSpecLifecycle.print_output( + "Acquisition Specification created with ID: " + acq_spec_id) + + # List Acquisition Specifications. + SampleAcquisitionSpecLifecycle.print_output( + "List of Acquisition Specifications", + self.acq_specs_client.list()) + + # Update the existing Acquisition Specification by only modifying the + # intended field in UpdateSpec, keeping all other fields as it is. + cid_mid_obj = CidMid(cid=new_cid) + counter_spec_obj = self.acq_specs_client.CounterSpec( + cid_mid=cid_mid_obj) + updated_acq_spec_obj = self.acq_specs_client.UpdateSpec( + counters=counter_spec_obj, + resources=[host_resource_id_obj], + interval=self.interval, + expiration=self.expiration, + memo_=memo + ) + self.acq_specs_client.update(acq_spec_id, updated_acq_spec_obj) + SampleAcquisitionSpecLifecycle.print_output( + "Updated Acquisition Specification", + self.acq_specs_client.get(acq_spec_id)) + + # Get the Acquisition Specification. + acq_spec_info = self.acq_specs_client.get(acq_spec_id) + SampleAcquisitionSpecLifecycle.print_output( + "Details of Acquisition Specification with ID " + acq_spec_id, + acq_spec_info) + + # Delete Acquisition Specification. + self.acq_specs_client.delete(acq_spec_id) + SampleAcquisitionSpecLifecycle.print_output( + "Acquisition Specification with ID: " + acq_spec_id + + " is deleted") + + @staticmethod + def print_output(*argv): + print("------------------------------------") + for arg in argv: + print(arg) + + +def main(): + """ + Entry point for the sample client. + """ + sample_acq_spec_lifecycle_obj = SampleAcquisitionSpecLifecycle() + sample_acq_spec_lifecycle_obj.run() + + +if __name__ == '__main__': + main() diff --git a/samples/vsphere/vcenter/vstats/data/__init__.py b/samples/vsphere/vcenter/vstats/data/__init__.py new file mode 100644 index 00000000..8e16649d --- /dev/null +++ b/samples/vsphere/vcenter/vstats/data/__init__.py @@ -0,0 +1,25 @@ +""" +* ******************************************************* +* Copyright VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__copyright__ = 'Copyright 2020 VMware, Inc. All rights reserved.' + + +# Required to distribute different parts of this +# package as multiple distribution +try: + import pkg_resources + pkg_resources.declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) # @ReservedAssignment diff --git a/samples/vsphere/vcenter/vstats/data/query_data_points.py b/samples/vsphere/vcenter/vstats/data/query_data_points.py new file mode 100644 index 00000000..c5e0f077 --- /dev/null +++ b/samples/vsphere/vcenter/vstats/data/query_data_points.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '7.0+' + +import random +import time + +from com.vmware.vstats_client import AcqSpecs, CidMid, RsrcId, Data +from vmware.vapi.vsphere.client import create_vsphere_client + +from samples.vsphere.common import sample_util +from samples.vsphere.common.ssl_helper import get_unverified_session +from samples.vsphere.vcenter.hcl.utils import get_configuration +from samples.vsphere.vcenter.vstats.helpers.sample_cli import parser + + +class SampleQueryDataPoints(object): + """ + Description: Demonstrates end to end workflow of vSphere Stats. + Step 1: Creation of an Acquisition Specification. + Step 2: Query for data points filtered by cid. + Sample Prerequisites: + vCenter 7.0x with 7.0x ESXi hosts. + """ + + def __init__(self): + args = sample_util.process_cli_args(parser.parse_args()) + self.interval = int(args.interval) + self.expiration = int(args.expiration) + + stub_config = get_configuration( + args.server, args.username, args.password, + args.skipverification) + self.acq_specs_client = AcqSpecs(stub_config) + self.data_client = Data(stub_config) + + session = get_unverified_session() if args.skipverification else None + self.vsphere_client = create_vsphere_client( + server=args.server, username=args.username, + password=args.password, session=session) + + def run(self): + cid = "disk.throughput.usage.VM" + wait_time = 30 + vm_type = "VM" + memo = "user definition of acquisition spec" + + cid_mid_obj = CidMid(cid=cid) + counter_spec_obj = self.acq_specs_client.CounterSpec( + cid_mid=cid_mid_obj) + + # Choose a random VM from which stats data needs to be collected. + vm_list = self.vsphere_client.vcenter.VM.list() + vm_obj = random.choice(vm_list) + vm_id = vm_obj.vm + + rsrc_obj = RsrcId(id_value=vm_id, type=vm_type) + + # Create an Acquisition Specification for VM counter. + acq_spec_obj = self.acq_specs_client.CreateSpec( + counters=counter_spec_obj, + resources=[rsrc_obj], + interval=self.interval, + expiration=self.expiration, + memo_=memo + ) + acq_spec_id = self.acq_specs_client.create(acq_spec_obj) + SampleQueryDataPoints.print_output( + "Acquisition Specification created with ID: " + acq_spec_id) + + # Get the Acquisition Specification. + acq_spec_info = self.acq_specs_client.get(acq_spec_id) + SampleQueryDataPoints.print_output( + "Details of Acquisition Specification with ID " + acq_spec_id, + acq_spec_info) + + # Wait for 30 seconds for data collection to happen. + time.sleep(wait_time) + + # Query for data points filtered by cid. + filter_spec = self.data_client.FilterSpec(cid=cid) + data_points = self.data_client.query_data_points(filter=filter_spec) + SampleQueryDataPoints.print_output( + "Data Points collected", data_points) + + # CleanUp. + # Delete the Acquisition Specification. + self.acq_specs_client.delete(acq_spec_id) + SampleQueryDataPoints.print_output( + "Acquisition Specification with ID: " + acq_spec_id + + " is deleted") + + @staticmethod + def print_output(*argv): + print("------------------------------------") + for arg in argv: + print(arg) + + +def main(): + """ + Entry point for the sample client. + """ + query_dp = SampleQueryDataPoints() + query_dp.run() + + +if __name__ == '__main__': + main() diff --git a/samples/vsphere/vcenter/vstats/data/query_data_points_set_id.py b/samples/vsphere/vcenter/vstats/data/query_data_points_set_id.py new file mode 100644 index 00000000..d4fb801e --- /dev/null +++ b/samples/vsphere/vcenter/vstats/data/query_data_points_set_id.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '7.0+' + +import random +import time + +from com.vmware.vstats_client import CounterSets, AcqSpecs, RsrcId, Data +from vmware.vapi.vsphere.client import create_vsphere_client + +from samples.vsphere.common import sample_util +from samples.vsphere.common.ssl_helper import get_unverified_session +from samples.vsphere.vcenter.hcl.utils import get_configuration +from samples.vsphere.vcenter.vstats.helpers.sample_cli import parser + + +class SampleQueryDataPointsSetID(object): + """ + Description: Demonstrates querying data points filtered by + resource by creating Acquisition Specification using + Counter SetId. + Sample Prerequisites: + vCenter 7.0x with 7.0x ESXi hosts. + """ + + def __init__(self): + args = sample_util.process_cli_args(parser.parse_args()) + self.interval = int(args.interval) + self.expiration = int(args.expiration) + + stub_config = get_configuration( + args.server, args.username, args.password, + args.skipverification) + self.counter_sets_client = CounterSets(stub_config) + self.acq_specs_client = AcqSpecs(stub_config) + self.data_client = Data(stub_config) + + session = get_unverified_session() if args.skipverification else None + self.vsphere_client = create_vsphere_client( + server=args.server, username=args.username, + password=args.password, session=session) + + def run(self): + wait_time = 30 + vm_type = "VM" + memo = "user definition of acquisition spec" + + # Get Counter-set ID of VM counters which is provided as + # Acquisition Specification setId. + counter_sets = self.counter_sets_client.list() + set_id = list(filter( + lambda cs: cs.counters[0].cid.endswith("." + vm_type), + counter_sets))[0].id + + counter_spec_obj = self.acq_specs_client.CounterSpec(set_id=set_id) + + # Choose a random VM from which stats data needs to be collected. + vm_list = self.vsphere_client.vcenter.VM.list() + vm_obj = random.choice(vm_list) + vm_id = vm_obj.vm + + rsrc_obj = RsrcId(id_value=vm_id, type=vm_type) + + # Create an Acquisition Specification for all the VM counters using + # "setId" in CreateSpec. + acq_spec_obj = self.acq_specs_client.CreateSpec( + counters=counter_spec_obj, + resources=[rsrc_obj], + interval=self.interval, + expiration=self.expiration, + memo_=memo + ) + acq_spec_id = self.acq_specs_client.create(acq_spec_obj) + SampleQueryDataPointsSetID.print_output( + "Acquisition Specification created with ID: " + acq_spec_id) + + # Get the Acquisition Specification. + acq_spec_info = self.acq_specs_client.get(acq_spec_id) + SampleQueryDataPointsSetID.print_output( + "Details of Acquisition Specification with ID: " + acq_spec_id, + acq_spec_info) + + # Wait for 30 seconds for data collection to happen. + time.sleep(wait_time) + + # Query for data points filtered by resource. + resource = "type." + vm_type + "=" + vm_id + filter_spec = self.data_client.FilterSpec(resources=[resource]) + data_points = self.data_client.query_data_points(filter=filter_spec) + SampleQueryDataPointsSetID.print_output( + "Data Points collected", data_points) + + # CleanUp. + # Delete the Acquisition Specification. + self.acq_specs_client.delete(acq_spec_id) + SampleQueryDataPointsSetID.print_output( + "Acquisition Specification with ID: " + acq_spec_id + + " is deleted") + + @staticmethod + def print_output(*argv): + print("------------------------------------") + for arg in argv: + print(arg) + + +def main(): + """ + Entry point for the sample client. + """ + query_dp = SampleQueryDataPointsSetID() + query_dp.run() + + +if __name__ == '__main__': + main() diff --git a/samples/vsphere/vcenter/vstats/data/query_data_points_with_predicate.py b/samples/vsphere/vcenter/vstats/data/query_data_points_with_predicate.py new file mode 100644 index 00000000..2ec8790d --- /dev/null +++ b/samples/vsphere/vcenter/vstats/data/query_data_points_with_predicate.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '7.0+' + +import random +import time + +from com.vmware.vstats_client import Providers, AcqSpecs, CidMid, RsrcId, Data + +from samples.vsphere.common import sample_util +from samples.vsphere.vcenter.hcl.utils import get_configuration +from samples.vsphere.vcenter.vstats.helpers.sample_cli import parser + + +class SampleQueryDataPointsPredicate(object): + """ + Description: Demonstrates querying data points filtered by cid + by creating Acquisition Specification using Query + Predicate "ALL". + Sample Prerequisites: + vCenter 7.0x with 7.0x ESXi hosts. + """ + + def __init__(self): + args = sample_util.process_cli_args(parser.parse_args()) + self.interval = int(args.interval) + self.expiration = int(args.expiration) + + stub_config = get_configuration( + args.server, args.username, args.password, + args.skipverification) + self.acq_specs_client = AcqSpecs(stub_config) + self.data_client = Data(stub_config) + self.providers_client = Providers(stub_config) + + def run(self): + cid = "disk.throughput.usage.VM" + wait_time = 30 + vm_type = "VM" + host_type = "HOST" + memo = "user definition of acquisition spec" + + cid_mid_obj = CidMid(cid=cid) + counter_spec_obj = self.acq_specs_client.CounterSpec( + cid_mid=cid_mid_obj) + + # To collect stats data from all VMs on a particular host, provide + # QueryPredicate "ALL" for VM resourceId. + rsrc_obj1 = RsrcId(id_value="", type=vm_type, predicate="ALL") + + # Choose a random host. + providers = self.providers_client.list() + random_host_id = random.choice(providers).id_value + + rsrc_obj2 = RsrcId(id_value=random_host_id, type=host_type) + + # Create an Acquisition Specification to collect stats data from all + # VMs on a host using QueryPredicate "ALL". + acq_spec_obj = self.acq_specs_client.CreateSpec( + counters=counter_spec_obj, + resources=[rsrc_obj1, rsrc_obj2], + interval=self.interval, + expiration=self.expiration, + memo_=memo + ) + acq_spec_id = self.acq_specs_client.create(acq_spec_obj) + SampleQueryDataPointsPredicate.print_output( + "Acquisition Specification created with ID: " + acq_spec_id) + + # Get the Acquisition Specification. + acq_spec_info = self.acq_specs_client.get(acq_spec_id) + SampleQueryDataPointsPredicate.print_output( + "Details of Acquisition Specification with ID: " + acq_spec_id, + acq_spec_info) + + # Wait for 30 seconds for data collection to happen. + time.sleep(wait_time) + + # Query for data points filtered by cid. + filter_spec = self.data_client.FilterSpec(cid=cid) + data_points = self.data_client.query_data_points(filter=filter_spec) + SampleQueryDataPointsPredicate.print_output( + "Data points collected", data_points) + + # CleanUp. + # Delete the Acquisition Specification. + self.acq_specs_client.delete(acq_spec_id) + SampleQueryDataPointsPredicate.print_output( + "Acquisition Specification with ID: " + acq_spec_id + + " is deleted") + + @staticmethod + def print_output(*argv): + print("------------------------------------") + for arg in argv: + print(arg) + + +def main(): + """ + Entry point for the sample client. + """ + query_dp = SampleQueryDataPointsPredicate() + query_dp.run() + + +if __name__ == '__main__': + main() diff --git a/samples/vsphere/vcenter/vstats/discovery.py b/samples/vsphere/vcenter/vstats/discovery.py new file mode 100644 index 00000000..8f4eced3 --- /dev/null +++ b/samples/vsphere/vcenter/vstats/discovery.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +""" +* ******************************************************* +* Copyright (c) VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '7.0+' + +import random + +from com.vmware.vstats_client import Counters, Providers, ResourceTypes, \ + CounterMetadata, Metrics, CounterSets, ResourceAddressSchemas + +from samples.vsphere.common import sample_cli, sample_util +from samples.vsphere.vcenter.hcl.utils import get_configuration + + +class SampleDiscovery(object): + """ + Description: Demonstrates all vSphere Stats discovery APIs which + give current state of the system. + Sample Prerequisites: + vCenter 7.0x with 7.0x ESXi hosts. + """ + + def __init__(self): + parser = sample_cli.build_arg_parser() + args = sample_util.process_cli_args(parser.parse_args()) + + stub_config = get_configuration( + args.server, args.username, args.password, + args.skipverification) + self.counters_client = Counters(stub_config) + self.providers_client = Providers(stub_config) + self.resource_types_client = ResourceTypes(stub_config) + self.counter_metadata_client = CounterMetadata(stub_config) + self.metrics_client = Metrics(stub_config) + self.counter_sets_client = CounterSets(stub_config) + self.resource_address_schemas_client = ResourceAddressSchemas( + stub_config) + + def run(self): + """ + Access the Discovery APIs to + List - counters, countermetadata, providers, resource types, + metrics, counter sets. + Get - resource address schema. + """ + # Counters List. + counters = self.counters_client.list() + SampleDiscovery.print_output("Counters List", counters) + + # Choose a random counter and provide cid as input to + # list CounterMetaData. + random_cid = random.choice(counters).cid + # List of counter metadata associated with that counter. + counter_metadata = self.counter_metadata_client.list(random_cid) + SampleDiscovery.print_output("Counter Metadata List", counter_metadata) + + # Choose a random counter and provide resource_address_schema_id as + # input to get Resource Address Schema. + random_resource_address_schema_id = random.choice(counters).\ + resource_address_schema + # Get resource address schema associated with that counter. + resource_address_schema = self.resource_address_schemas_client.get( + random_resource_address_schema_id) + SampleDiscovery.print_output("Resource Address Schema", + resource_address_schema) + + # List of vSphere Stats providers connected to vCenter Server. + providers = self.providers_client.list() + SampleDiscovery.print_output("Providers List", providers) + + # List of resource types supported by vSphere Stats. + resource_types = self.resource_types_client.list() + SampleDiscovery.print_output("Resource Types List", resource_types) + + # List of metrics supported by vSphere Stats. + metrics = self.metrics_client.list() + SampleDiscovery.print_output("Metrics List", metrics) + + # List of vSphere Stats defined Counter-sets. + counter_sets = self.counter_sets_client.list() + SampleDiscovery.print_output("Counter Sets List", counter_sets) + + @staticmethod + def print_output(*argv): + print("------------------------------------") + for arg in argv: + print(arg) + + +def main(): + """ + Entry point for the sample client. + """ + discovery = SampleDiscovery() + discovery.run() + + +if __name__ == '__main__': + main() diff --git a/samples/vsphere/vcenter/vstats/helpers/__init__.py b/samples/vsphere/vcenter/vstats/helpers/__init__.py new file mode 100644 index 00000000..8e16649d --- /dev/null +++ b/samples/vsphere/vcenter/vstats/helpers/__init__.py @@ -0,0 +1,25 @@ +""" +* ******************************************************* +* Copyright VMware, Inc. 2020. All Rights Reserved. +* SPDX-License-Identifier: MIT +* ******************************************************* +* +* DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +* EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +* WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +* NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. +""" + +__author__ = 'VMware, Inc.' +__copyright__ = 'Copyright 2020 VMware, Inc. All rights reserved.' + + +# Required to distribute different parts of this +# package as multiple distribution +try: + import pkg_resources + pkg_resources.declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) # @ReservedAssignment diff --git a/samples/vsphere/vcenter/vstats/helpers/sample_cli.py b/samples/vsphere/vcenter/vstats/helpers/sample_cli.py new file mode 100644 index 00000000..09130199 --- /dev/null +++ b/samples/vsphere/vcenter/vstats/helpers/sample_cli.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +""" + * ******************************************************* + * Copyright (c) VMware, Inc. 2020. All Rights Reserved. + * SPDX-License-Identifier: MIT + * ******************************************************* + * + * DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, + * EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED + * WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, + * NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. + """ + +__author__ = 'VMware, Inc.' +__vcenter_version__ = '7.0+' + +from samples.vsphere.common.sample_cli import build_arg_parser + +""" +Builds a standard argument parser with required and optional argument groups +Most of the Vsphere Stats samples require these three standard required +arguments. +--expiration +--interval +""" +parser = build_arg_parser() + +required_args = parser.add_argument_group( + 'required arguments for creating acquisition spec') + +required_args.add_argument( + '--expiration', + required=True, + help='Create an Acquisition Specification with expiration time.' + + ' Example: 10000000000') + +required_args.add_argument( + '--interval', + required=True, + help='Create an Acquisition Specification with interval. Example: 10') diff --git a/setup.py b/setup.py index 4b9cfaa6..5885c1c6 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ import os from setuptools import setup setup(name='vSphere Automation SDK', - version='1.18.0', + version='1.19.0', description='VMware vSphere Automation SDK for Python', url='https://github.com/vmware/vsphere-automation-sdk-python', author='VMware, Inc.', @@ -15,10 +15,10 @@ setup(name='vSphere Automation SDK', 'suds ; python_version < "3"', 'suds-jurko ; python_version >= "3.0"', 'pyVmomi >= 6.7', - 'vapi-runtime @ file://localhost/{}/lib/vapi-runtime/vapi_runtime-2.12.0-py2.py3-none-any.whl'.format(os.getcwd()), - 'vapi-client-bindings @ file://localhost/{}/lib/vapi-client-bindings/vapi_client_bindings-3.1.0-py2.py3-none-any.whl'.format(os.getcwd()), - 'vapi-common-client @ file://localhost/{}/lib/vapi-common-client/vapi_common_client-2.12.0-py2.py3-none-any.whl'.format(os.getcwd()), - 'vmc-client-bindings @ file://localhost/{}/lib/vmc-client-bindings/vmc_client_bindings-1.21.0-py2.py3-none-any.whl'.format(os.getcwd()), + 'vapi-runtime @ file://localhost/{}/lib/vapi-runtime/vapi_runtime-2.14.0-py2.py3-none-any.whl'.format(os.getcwd()), + 'vapi-client-bindings @ file://localhost/{}/lib/vapi-client-bindings/vapi_client_bindings-3.2.0-py2.py3-none-any.whl'.format(os.getcwd()), + 'vapi-common-client @ file://localhost/{}/lib/vapi-common-client/vapi_common_client-2.14.0-py2.py3-none-any.whl'.format(os.getcwd()), + 'vmc-client-bindings @ file://localhost/{}/lib/vmc-client-bindings/vmc_client_bindings-1.21.0-py2.py3-none-any.whl'.format(os.getcwd()), 'nsx-python-sdk @ file://localhost/{}/lib/nsx-python-sdk/nsx_python_sdk-2.5.1.0.1.15419398-py2.py3-none-any.whl'.format(os.getcwd()), 'nsx-policy-python-sdk @ file://localhost/{}/lib/nsx-policy-python-sdk/nsx_policy_python_sdk-2.5.1.0.1.15419398-py2.py3-none-any.whl'.format(os.getcwd()), 'nsx-vmc-policy-python-sdk @ file://localhost/{}/lib/nsx-vmc-policy-python-sdk/nsx_vmc_policy_python_sdk-2.5.1.0.1.15419398-py2.py3-none-any.whl'.format(os.getcwd()),