###
# (C) Copyright [2019] Hewlett Packard Enterprise Development LP
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
"""Implements features available for Virtual Machine resource."""
from simplivity.resources.resource import ResourceBase
from simplivity.resources import datastores
from simplivity.resources import omnistack_clusters
from simplivity.resources import backups
from simplivity.resources import policies
URL = '/virtual_machines'
DATA_FIELD = 'virtual_machines'
[docs]class VirtualMachines(ResourceBase):
"""Implements features for SympliVity VM resources."""
def __init__(self, connection):
"""Initialize VirtualMachines class."""
super(VirtualMachines, self).__init__(connection)
[docs] def get_all(self, pagination=False, page_size=0, limit=500, offset=0,
sort=None, order='descending', filters=None, fields=None,
case_sensitive=True, show_optional_fields=False):
"""Get all vms.
Args:
pagination: True if need pagination
page_size: Size of the page (Required when pagination is on)
limit: A positive integer that represents the maximum number of results to return
offset: A positive integer that directs the service to start returning
the <offset value> instance, up to the limit.
sort: The name of the field where the sort occurs.
order: The sort order preference. Valid values: ascending or descending.
filters: Dictionary with filter values. Example: {'name': 'name'}
id: The unique identifier (UID) of the virtual_machines to return
Accepts: Single value, comma-separated list
name: The name of the virtual_machines to return
Accepts: Single value, comma-separated list, pattern using one or more
asterisk characters as a wildcard
omnistack_cluster_id: The unique identifier (UID) of the omnistack_cluste
that is associated with the instances to return
Accepts: Single value, comma-separated list
omnistack_cluster_name: The name of the omnistack_cluster that
is associated with the instances to return.
Accepts: Single value, comma-separated list.
compute_cluster_parent_hypervisor_object_id: The unique identifier (UID)
of the hypervisor that contains the omnistack_cluster that is associated
with the instances to return
Accepts: Single value, comma-separated list.
compute_cluster_parent_name: The name of the hypervisor that contains the
omnistack_cluster that is associated with the instances to return
Accepts: Single value, comma-separated list
hypervisor_management_system: The IP address of the hypervisor associated
with the virtual machine.
Accepts: Single value, comma-separated list, pattern using one
or more asterisk characters as a wildcard
hypervisor_management_system_name: The name of the hypervisor associated
with the virtual machine
Accepts: Single value, comma-separated list, pattern using one or more
asterisk characters as a wildcard
datastore_id: The unique identifier (UID) of the datastore that is associated
with the instances to return
Accepts: Single value, comma-separated list
datastore_name: The name of the datastore that is associated with the
instances to return
Accepts: Single value, comma-separated list
policy_id: The unique identifier (UID) of the policy that is associated
with the instances to return
Accepts: Single value, comma-separated list
policy_name: The name of the policy that is associated with the instances to return
Accepts: Single value, comma-separated list
hypervisor_object_id: The unique identifier (UID) of the hypervisor-based instance
that is associated with the instances to return
Accepts: Single value, comma-separated list
created_after: The earliest creation time after the virtual machines to return were
created, expressed in ISO-8601 form, based on Coordinated Universal Time (UTC)
created_before: The latest creation time before the virtual machines to return were
created, expressed in ISO-8601 form, based on Coordinated Universal Time (UTC)
state: The state of the virtual_machine that is associated with the instances to return
Accepts: Single value, comma-separated list
app_aware_vm_status: The status of the ability of the virtual machine to take
an application-consistent backup that uses Microsoft VSS
Accepts: Single value, comma-separated list
hypervisor_is_template: An indicator that shows if the virtual machine is a template.
host_id: The unique identifier (UID) of the virtual_machine host.
fields: A comma-separated list of fields to include in the returned objects
case_sensitive: An indicator that specifies if the filter and sort results
use a case-sensitive or insensitive manner.
show_optional_fields: An indicator to show or not show the ha_status,
ha_resynchronization_progress, hypervisor_virtual_machine_power_state,
and hypervisor_is_template.
Returns:
list/pagination object: list of VirtualMachine objects/ Pagination object
"""
return self._client.get_all(URL,
members_field=DATA_FIELD,
pagination=pagination,
page_size=page_size,
limit=limit,
offset=offset,
sort=sort,
order=order,
filters=filters,
fields=fields,
case_sensitive=case_sensitive,
show_optional_fields=show_optional_fields)
[docs] def get_by_data(self, data):
"""Gets VM object from VM data.
Args:
data: VM data
Returns:
object: Virtual Machine object.
"""
return VirtualMachine(self._connection, self._client, data)
[docs] def set_policy_for_multiple_vms(self, policy, vms, timeout=-1):
"""Sets the backup policy for virtual machines.
Args:
vms: list of vm objects
policy: policy object
"""
method_url = "{}/set_policy".format(URL)
vm_ids = [vm.data["id"] for vm in vms]
policy_id = policy.data["id"]
data = {"virtual_machine_id": vm_ids,
"policy_id": policy_id}
affected_resources = self._client.do_post(method_url, data, timeout, None)
vm_ids = [resource["object_id"] for resource in affected_resources]
comma_separated_ids = ','.join(vm_ids)
return self.get_all(filters={'id': comma_separated_ids})
[docs] def policy_impact_report(self, policy, vms, timeout=-1):
"""Generate a backup impact reported based on proposed application of a policy to one or more virtual machines.
Args:
policy: Policy object/name
vms: List of vm objects
timeout: Time out for the request in seconds.
Returns:
dict: Returns the dictionary for impact report of policy applied on virtual machines.
"""
method_url = "{}/policy_impact_report/apply_policy".format(URL)
custom_headers = {'Content-type': 'application/vnd.simplivity.v1.14+json'}
vm_ids = [vm.data["id"] for vm in vms]
if not isinstance(policy, policies.Policy):
# if passed name of the policy
policy = policies.Policies(self._connection).get_by_name(policy)
data = {"virtual_machine_id": vm_ids,
"policy_id": policy.data["id"]}
return self._client.do_post(method_url, data, timeout, custom_headers)
[docs]class VirtualMachine(object):
"""Implements features available for a single VM."""
def __init__(self, connection, resource_client, data):
"""Initialize with connection object, resource client and VM data"""
self.data = data
self._connection = connection
self._client = resource_client
self._vms = VirtualMachines(self._connection)
def __refresh(self):
"""Updates the VM data."""
resource_uri = "{}/{}".format(URL, self.data["id"])
self.data = self._client.do_get(resource_uri)['virtual_machine']
[docs] def clone(self, new_vm_name, app_consistent=False, datastore=None, timeout=-1):
"""Clones a virtual machine.
Args:
new_vm_name: The name of the virtual_machine created from this action.
app_consistent: An indicator to show if the backup represents a snapshot
of a virtual machine with data that was first flushed to disk.
datastore: Object/name of the datastore.
if passed, new VM will be moved to the datastore.
timeout: Time out for the request in seconds.
Returns:
object: Object of the new VM
"""
method_url = "{}/{}/clone".format(URL, self.data["id"])
data = {"virtual_machine_name": new_vm_name,
"app_consistent": app_consistent}
out = self._client.do_post(method_url, data, timeout, None)
vm = self._vms.get_by_id(out[0]["object_id"])
if datastore:
return vm.move(new_vm_name, datastore)
return vm
[docs] def move(self, new_vm_name, datastore, timeout=-1):
"""Moves a virtual machine to another datastore.
Args:
new_vm_name: Name of the new vm
datastore: Object/name of the destination datastore
timeout: Time out for the request in seconds.
Returns:
VirtualMachine object: Object of the moved VM
"""
method_url = "{}/{}/move".format(URL, self.data["id"])
if not isinstance(datastore, datastores.Datastore):
# if passed name of the datastore
datastores_obj = datastores.Datastores(self._connection)
datastore = datastores_obj.get_by_name(datastore)
data = {"virtual_machine_name": new_vm_name,
"destination_datastore_id": datastore.data["id"]}
affected_object = self._client.do_post(method_url, data, timeout, None)[0]
vm_obj = self._vms.get_by_id(affected_object["object_id"])
self.data = vm_obj.data
return self
[docs] def create_backup(self, backup_name, cluster=None, app_consistent=False,
consistency_type=None, retention=0, timeout=-1):
"""Backs up a virtual machine.
Args:
backup_name: The name of the new backup created from this action.
cluster: Destination OmnistackCluster object/name.
app_consistent: An indicator to show if the backup represents
a snapshot of a virtual machine with data that was first flushed to disk.
consistency_type: The consistency type of the backup.
retention: The number of minutes to keep backups.
timeout: Time out for the request in seconds.
Returns:
Backup object: object of the newly created backup.
"""
method_url = "{}/{}/backup".format(URL, self.data["id"])
if cluster and not isinstance(cluster, omnistack_clusters.OmnistackCluster):
# if passed name of the omnistack cluster
clusters_obj = omnistack_clusters.OmnistackClusters(self._connection)
cluster = clusters_obj.get_by_name(cluster)
data = {"backup_name": backup_name,
"app_consistent": app_consistent,
"consistency_type": consistency_type,
"retention": retention}
if cluster:
data["destination_id"] = cluster.data["id"]
backup = self._client.do_post(method_url, data, timeout, None)[0]
return backups.Backups(self._connection).get_by_id(backup["object_id"])
[docs] def get_backups(self):
"""Retrieves all backups associated with this virtual_machine.
Returns:
list: List of backup objects
"""
method_url = "{}/{}/backups".format(URL, self.data["id"])
backup_data = self._client.do_get(method_url).get("backups", [])
backup_objs = []
for backup in backup_data:
obj = backups.Backups(self._connection).get_by_id(backup["id"])
backup_objs.append(obj)
return backup_objs
[docs] def set_backup_parameters(self, guest_username, guest_password, override_guest_validation=False,
app_aware_type=None, timeout=-1):
"""Set the virtual machine backup parameters used for application consistent backups.
Args:
guest_username: Username of the virtual machine.
guest_password: Password of the virtual machine.
override_guest_validation: Set to true to disable virtual machine validation logic.
app_aware_type: Set the application aware backup type:
VSS - Application-consistentbackup using Microsoft VSS
DEFAULT - Crash-consistent
NONE - Application-consistent backup using a VMware snapshot
timeout: Time out for the request in seconds.
Returns:
self: Returns the same object.
"""
method_url = "{}/{}/backup_parameters".format(URL, self.data["id"])
data = {"guest_username": guest_username,
"guest_password": guest_password,
"override_guest_validation": override_guest_validation,
"app_aware_type": app_aware_type}
self._client.do_post(method_url, data, timeout, None)
self.__refresh()
return self
[docs] def set_policy(self, policy, timeout=-1):
"""Sets the backup policy for virtual machine.
Args:
policy: Policy object/name
timeout: Time out for the request in seconds.
Returns:
self: Returns the same object.
"""
method_url = "{}/{}/set_policy".format(URL, self.data["id"])
if not isinstance(policy, policies.Policy):
# if passed name of the policy
policy = policies.Policies(self._connection).get_by_name(policy)
data = {"policy_id": policy.data["id"]}
self._client.do_post(method_url, data, timeout, None)
self.__refresh()
return self
[docs] def power_off(self, timeout=-1):
"""Power off virtual machine.
Args:
timeout: Time out for the request in seconds.
Returns:
self: Returns the same object.
"""
method_url = "{}/{}/power_off".format(URL, self.data["id"])
custom_headers = {'Content-type': 'application/vnd.simplivity.v1.11+json'}
self._client.do_post(method_url, None, timeout, custom_headers)
self.__refresh()
if self.data["hypervisor_virtual_machine_power_state"] == "OFF":
return True
else:
return False
[docs] def power_on(self, timeout=-1):
"""Power on virtual machine.
Args:
timeout: Time out for the request in seconds.
Returns:
self: Returns True if successfully power on the VM else False.
"""
method_url = "{}/{}/power_on".format(URL, self.data["id"])
custom_headers = {'Content-type': 'application/vnd.simplivity.v1.14+json'}
self._client.do_post(method_url, None, timeout, custom_headers)
self.__refresh()
if self.data["hypervisor_virtual_machine_power_state"] == "ON":
return True
else:
return False
[docs] def validate_backup_credentials(self, guest_username, guest_password, timeout=-1):
"""Validates the credentials for the virtual machine want to backup.
Args:
guest_username: Username of the virtual machine.
guest_password: Password of the virtual machine.
timeout: Time out for the request in seconds.
Returns:
status: Possible values are 'VALID', 'INVALID'.
"""
method_url = "{}/{}/validate_backup_credentials".format(URL, self.data["id"])
data = {"guest_username": guest_username,
"guest_password": guest_password}
status = self._client.do_post(method_url, data, timeout)
return status['credentials_validation']['status']
[docs] def get_metrics(self, time_offset=0, range=43200, resolution='MINUTE'):
"""Retrieves throughput, IOPS, and latency data for the virtual machine
Args:
time_offset: A time offset in seconds (from now) or a datetime,
expressed in ISO-8601 form, based on Coordinated Universal Time (UTC) Default: 0
range: A range in seconds (the duration from the specified point in time) Default: 43200
resolution: The resolution (SECOND, MINUTE, HOUR, or DAY) Default: MINUTE
Returns:
dict: Dictionary of metrics object.
"""
method_url = "{}/{}/metrics".format(URL, self.data["id"])
filters = {'time_offset': time_offset, 'range': range, 'resolution': resolution}
return self._client.do_get(method_url, filters)