Control Hyper-V VMs with Python - python

im trying to write a control VMs on a HyperV Server using Python. I start with connecting to the server the HyperV server runs on:
connection = wmi.connect_server(server="servername", namespace=r"root\virtualization", user=r"username", password=r"password")
wmiServerConnection = wmi.WMI(wmi=connection)
This gives me a wmi object for this connection.
For stopping and starting a VM I can simply use:
#get the wmi object representing the VM
vmSystem = wmiServerConnection.Msvm_ComputerSystem(ElementName="VmName")
#send change request to vm
vmSystem[0].RequestStateChange(3)
But before starting a VM I want to apply a certain snapshot.
The class Msvm_VirtualSystemManagementService provides a method - ApplyVirtualSystemSnapshot/ApplyVirtualSystemSnapshotEx - for this. It needs the SnapshotSettingData as a parameter and I thought I could get that one using the GetSummaryInformation method of the same class. MSDN says this method returns a Msvm_SummaryInformation class.
I call this function like this:
#get the wmi class object
vmManagement = wmiServerConnection.Msvm_VirtualSystemManagementService()
snapshotInfo = vmManagement[0].GetSummaryInformation([1,107])
This should give me the name and the snapshot information for all VMs on the HyperV server. But all I get is list of COM Objects.
When I try to give a certain VM as parameter gotten from
vmSettings = wmiServerConnection.Msvm_VirtualSystemSettingData(ElementName="VmName")
like this
snapshotInfo = vmManagement[0].GetSummaryInformation([1,107], [vmSettings[0]])
it crashes.
My questions:
Why don't I get a WMI object?
The second parameter is obviously wrong. MSDN says it needs CIM_VirtualSystemSettingData REF SettingData[] as parameter. Is the WMI object the wrong one? How do I get the correct parameter?
How can I retrieve the information I need from the COM object?
Or am I totally on the wrong track?
Thanks, Stefanie

So, I finally found the solution. It was much easier than I thought, but whatever:
1.Connect to your server and get the WMI-object:
connection = wmi.connect_server(server=serverName, namespace=r"root\virtualization", user=username, password=password)
wmiServerConnection = wmi.WMI(wmi=connection)
2.Get the system object and the management service object:
#get object representing VM
vmSystem = wmiServerConnection.Msvm_ComputerSystem(ElementName=VmName)
#get object responsible for VM
vmManagement = wmiServerConnection.Msvm_VirtualSystemManagementService()
3.Get the objects associated with the VM:
#get objects the VM contains
vmObjects = vmSystem[0].associators(wmi_result_class="Msvm_VirtualSystemSettingData ")
4.Apply the snapshot you want:
for singleVmObject in vmObjects:
if(singleVmObject.SettingType == 5 and singleVmObject.ElementName == snapshotName):
retVal = vmManagement[0].ApplyVirtualSystemSnapshotEx(vmSystem[0].path(), singleVmObject.path())
Further documentation can be found here:
http://timgolden.me.uk/python/wmi/wmi.html
http://msdn.microsoft.com/en-us/library/cc136986(v=vs.85).aspx

Related

How can I delete an ethernet interface from a firewall using PAN's Python bindings?

I'm trying to understand how to read the following documentation:
https://pandevice.readthedocs.io/en/latest/readme.html
This is something I need to learn how to do, but I'm having difficulty doing simple tasks.. Some I can get to work correctly, some I just can't see how to get working.
For example. If I were to add an interface and IP address:
from panos import device, firewall, network
fw_ip = "1.2.3.4"
api_username = "admin"
api_password = "pass123!"
#connect to firewall
fw = firewall.Firewall(fw_ip, api_username=api_username, api_password=api_password)
#create interface
interface = network.EthernetInterface(name="ethernet1/5", mode="layer3", ip="192.168.0.1/24")
fw.add(interface)
interface.create()
That is straight forward. But I can't for the life of me figure out how to replace/remove/delete/change any elements in an interface. I KNOW this is a matter of me not understanding the documentation. Here's my attempt thus far:
interface = network.EthernetInterface(name='ethernet1/5')
fw.delete(interface)
interface.create()
but I get the following error:
TypeError: delete() takes 1 positional argument but 2 were given
The other methods the documentation point out are remove() and delete() but neither work.
I have a feeling this will be an easy one for someone who reads these often.
Thanks.

OCI: How to create a boot volume from an existing volume's using the oci sdk

I want to use the OCI python sdk to create a boot volume.
So i have the id from the source compute instance's boot volume ID.
Below i try to do it using BootVolumeSourceFromBootVolumeDetails(). If i was passing in the id this would give me the error in python.
"init takes 1 argument but you passed 2"
Here is my code
def create_boot_volume_and_wait_for_state(source_boot_volume_id,
compartment_id,
source='boot_volume_details',
wait_for_states=BootVolume.LIFECYCLE_STATE_AVAILABLE,
operation_kwargs=None, waiter_kwargs=None,
**model_kwargs):
source_details = BootVolumeSourceFromBootVolumeDetails()
availability_domain = ComputeRestUtils.get_first_availability_domain(compartment_id)
create_boot_volume_details = CreateBootVolumeDetails(
availability_domain=availability_domain.name,
display_name="test",
compartment_id=compartment_id,
source_details=source_details,
**model_kwargs)
How do i link it to the instance's boot volume?
BootVolumeSourceFromBootVolumeDetails requires two arguments type and source id something as below.
source_details=oci.core.models.BootVolumeSourceFromBootVolumeDetails(
type="bootVolume",
id="ocid1.bootvolume.oc1.iad.<MASKED>")))
You may find a complete sample at https://github.com/oracle-devrel/oci-sdk-python-samples/tree/main/samples/create-boot-volume
You may also refer to OCI SDK documentation at https://docs.oracle.com/en-us/iaas/tools/python/2.79.0/api/core/models/oci.core.models.BootVolumeSourceFromBootVolumeDetails.html#oci.core.models.BootVolumeSourceFromBootVolumeDetails

How to create and use objects from the Inventor COM API in python (pywin32)

I'm attempting to use Autodesk Inventor's COM API to create a python script that will generate PDFs of a selection on Inventor Drawings, these PDFs will then be processed in particular ways that aren't important to my question. I'm using pywin32 to access the COM API, but I'm not particularly familiar with how COM APIs are used, and the pywin32 module.
This is the extent of the documentation for Inventor's API that I have been able to find (diagram of API Object Model Reference Document), and I have not been able to find documentation for the individual objects listed. As such, I'm basing my understanding of the use of these objects on what I can find from examples online (all in VB or iLogic - Inventor's own simple built-in language).
A big issue I'm coming up against is in creating the objects I'd like to use. Simplified example below:
from win32com.client import *
# user chooses file paths for open and save here...
drawing_filepath = ""
# Open Inventor application, and set visible (so I can tell it's opened for now)
app = Dispatch('Inventor.Application')
app.Visible = True
# Open the file to be saved as a pdf (returns a Document object)
app.Documents.Open(drawing_filepath)
# Cast the opened Document object to a DrawingDocument object (it is guaranteed to be a drawing)
drawing = CastTo(app.ActiveDocument, "DrawingDocument")
# Create and setup a print manager (so can use "Adobe PDF" printer to convert the drawings to PDF)
print_manager = ??? # How can I create this object
# I've tried:
# print_manager = Dispatch("Inventor.Application.Documents.DrawingDocument.DrawingPrintManager") #"Invalid class string"
# print_manager = drawing.DrawingPrintManager() #"object has no attribute 'DrawingPrintManger'
# print_manager = drawing.DrawingPrintManager # same as above
# print_manager = drawing.PrintManger # worked in the end
print_manager.Printer = "Adobe PDF"
print_manager.NumberOfCopies = 1
print_manager.ScaleMode = print_manager.PrintScaleModeEnum.kPrintFullScale
print_manager.PaperSize = print_manager.PrintSizeEnum.kPaperSizeA3
# Print PDF
print_manager.SubmitPrint()
So I can't figure out how to create a DrawingPrintManager to use! You can see I've avoided this issue when creating my DrawingDocument object, as I just happened to know that there is an ActiveDocument attribute that I can get from the application itself.
I also:
don't know what the full list of attributes and methods for DrawingPrintManager are, so I don't know how to set a save location
don't know for sure that the two Enums I'm trying to use are actually defined within DrawingPrintManager, but I can figure that out once I actually have a DrawingPrintManager to work with
If anyone with more experience in using COM APIs or pywin32 can help me out, I'd be really appreciative. And the same if anyone can point me towards any actual documentation of Inventor's API Objects, which would make things a lot easier.
Thanks
Edit: After posting I've almost immediately found that I can get a PrintManager (can't tell if a PrintManager or DrawingPrintManager) by accessing drawing.PrintManager rather than drawing.DrawingPrintManager.
This is a workaround however as it doesn't answer my question of how to create objects within pywin32.
My problem moving forward is finding where I can access the PrintScaleModeEnum and PrintSizeEnum objects, and finding how to set the save location of the printed PDF (which I think will be a a separate question, as it's probably unrelated to the COM API).
I'm not familiar with python and pywin32, but I try to answer your questions.
Documentation of Inventor API is available in local installation "C:\Users\Public\Documents\Autodesk\Inventor 2020\Local Help" or online https://help.autodesk.com/view/INVNTOR/2020/ENU/
Generaly you are not able to create new instances of Inventor API objects. You must obtain them as a result of appropriate method or property value.
For example:
You CAN'T do this
doc = new Inventor.Document()
You MUST do this
doc = app.Documents.Add(...)
With print manager is this
print_manager = drawing.PrintManger
# this returns object of type Inventor.DrawingPrintManager
# when drawing is of type Inventor.DrawingDocument
See this for more details

win32com.client.Dispatch works, win32com.client.GetActiveObject doesnt

Im using python 2.7.9, windows 7...
The overall goal: Have another application access our custom com server (already running at this point) and send it a message to be displayed. Obviously, there needs to be a single server, multiple clients.
Im trying to use some custom code as a com server. The class was created as:
class StatusServerClass:
_public_methods_ = ...
_reg_progid_ = "CseStatusServerLib.CseStatusServer"
_reg_verprogid_ = "CseStatusServerLib.CseStatusServer"
_reg_progid_ = "CseStatusServerLib.CseStatusServer"
_reg_clsid_ = "{<GUID here>}"
_reg_desc_ = 'CSE Status Server'
_typelib_guid_ = "{<typelib GUID here>}"
_typelib_version_ = 1, 0 # Version 1.0
_reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER
_reg_threading_ = "Apartment" # Not used?
def __init__.....
and registered using:
win32com.server.register.UseCommandLine(StatusServerClass)
I can see it in regedit and as far as i know, it looks ok.
The GUID is right, name is right.
Now when i go to use it, this works just fine:
self.StatusClient = Dispatch('CseStatusServerLib.CseStatusServer')
but when i want to attach to a running instance from another exe (or even another python window for debug) using:
win32com.client.GetActiveObject("CseStatusServerLib.CseStatusServer")
it just gives me:
dispatch = pythoncom.GetActiveObject(resultCLSID)
com_error: (-2147221021, 'Operation unavailable', None, None)
Tells me that its not registered?
Ive tried using the GUID, Ive tried using pythoncom.GetObject with both the ID and the GUID... no luck.
Ive tried comtypes package and get the same thing.
Any ideas on what im doing wrong? Why does Dispatch find it by name, but GetActiveObject gets mad?
Seems that Dispatch working by name would suggest that the registering worked?
What else can i verify in the regedit?
thanks!!!
UPDATED 6/6/2016
In case you haven't realized yet, I know very little about this. But I have read that for win32com.client.GetActiveObject() to work, the server needs to be in the "running object table"... and its not.
So, I found some more example code that i used to register the class this way:
import win32com.server.util
wrapped = win32com.server.util.wrap(StatusServerClass)
flags = pythoncom.REGCLS_MULTIPLEUSE|pythoncom.REGCLS_SUSPENDED
handle = pythoncom.RegisterActiveObject(wrapped,
StatusServerClass._reg_clsid_,flags)
and that does allow the server to show in the running object table, and i can get this:
testSW = win32com.client.GetActiveObject("CseStatusServerLib.CseStatusServer")
to return without error.
So now, I can use Dispatch or GetActiveObject just fine in python, pythonWin, and even interact with the server in Excel/VB <-> python and it appears to share namespsace.
BUT...
I still cant get this IE-based third party app to use the existing server... even with GetActiveObject. Always wants to create new instance and use its own namespace... not good
Is there something with IE or Chrome that would prevent the existing server from being used? Again, it works fine in Excel/VB. The application is supposed to execute "python myscript.py" (which works fine in idle, pythonwin and cmdline), but doesnt execute the com server stuff when called from IE/Chrome App (although other python functions like file writing work just fine).
Also, seeing as how i know very little about this, by all means, suggest a better way of doing this: starting a server in python as a singleton and then accessing it from another application.
thanks!!

pyvmomi retrieving vim.host.Summary.QuickStats

At this moment i am tryging to retrieve the quickstats of an ESXI host itself.
This is the way i connect :
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.verify_mode = ssl.CERT_NONE
si = SmartConnect(host=args.host,
user=args.user,
pwd=password,
port=int(args.port),
sslContext=context)
How do i retrieve the following stats with this library?
https://github.com/vmware/pyvmomi/blob/master/docs/vim/host/Summary/QuickStats.rst
First you need to locate your host, then access the properties like so:
content = si.RetrieveContent()
host = content.searchIndex.FindByDnsName(dnsName="DC0_C0_H0", vmSearch=False)
print host.summary.quickStats.uptime
The method Im using to locate the host does not have to be used.. its just one of MANY ways of finding a host.. This example assumes you only need to do this for 1 or 2 hosts... Assuming you have lots of hosts and dont want the call to be slow you would really want to build a property collector to fetch that data or else the call will take ages.. If you look at the community samples there is an example or 2 that use views and property collectors which will make your code fast and scaleable.

Categories