I was asked to write some python code that would put an VMWare ESXi host into maintenance mode. I was given the name of a virtual center, test-vc, and the hostname of an ESXi host, test-esxi-host and this link ...
https://github.com/vmware/pyvmomi/blob/master/docs/vim/HostSystem.rst
... which provides some documentation on the method I am suppose to use, EnterMaintenanceMode(timeout, evacuatePoweredOffVms, maintenanceSpec).
I am really a complete loss as to what to do really and could use some help. I have tried doing this from a python console:
from pyVmomi import vim
vim.HostSystem.EnterMaintenanceMode(timeout=0)
Which results in this error trace:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/apps/cpm/red/env/lib/python2.7/site-packages/pyVmomi/VmomiSupport.py", line 574, in __call__
return self.f(*args, **kwargs)
TypeError: _InvokeMethod() takes at least 2 arguments (1 given)
Also I am a kind of confused about how the EnterMaintenanaceMode routine would know that I want to put the host test-esxi-host in virtual center test-vc?
Update: I think I have figured it out. Here's what I think I need to do:
from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vim
import atexit
si = SmartConnectNoSSL(host=vc_host, user=user, pwd=pwd)
cont = si.RetrieveContent()
atexit.register(Disconnect, si) # maybe. I am not really sure what this does
objview = si.content.viewManager.CreateContainerView(si.content.rootFolder, [vim.HostSystem], True)
objview.view[0].EnterMaintenanceMode(0)
Of course the line
objview.view[0].EnterMaintenanceMode(0)
is sure to wreak havoc as I have no idea if that is the host, 'test-esxi-host', I want to put into maintenance mode. I guess I could do this
for h in objview.view:
if h.name == 'test-esxi-host'
h.EnterMaintenanceMode(0)
I hope there is a better way to do the above. Something like
get_host(objview.view, 'test-esxi-host').EnterMaintenanceMode(0)
Have a look at Getting started with VMwares ESXi/vSphere API in Python.
To get a VM object or a list of objects you can use the searchIndex
class. The class had methods to search for VMs by UUID, DNS name, IP
address or datastore path.
Hopefuly, there are a couple of ways to look for objects in vCenter:
FindByUuid (VM|Host)
FindByDatastorePath (VM)
FindByDnsName (VM|Host)
FindByIp (VM|Host)
FindByInventoryPath (managed entity: VM|Host|Resource Pools|..)
FindChild (managed entity)
Many of these also have FindAll.. methods which allow a much broader look up.
For this particular case, you could use FindByDnsName to look for your host.
searcher = si.content.searchIndex
host = searcher.FindByDnsName(dnsName='test-esxi-host', vmSearch=False)
host.EnterMaintenanceMode(0)
This code requires you to authenticate to vCenter (#SmartConnectNoSSL) with a user having Host.Config.Maintenance privileges.
Finally you can take your host out of maintenance mode with: host.ExitMaintenanceMode(0)
Related
The whois.whois function always gets a timed out error.
At first, I thought it was because my project is written in Python 2.7 but I also checked in 3.7 and got the same error.
I checked the address on the online website that uses whois and the link worked and didn't get this error.
Anyone knows why this is happening?
import whois
w = whois.whois("https://stackoverflow.com")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Python37\lib\site-packages\whois\__init__.py", line 43, in whois
text = nic_client.whois_lookup(None, domain.encode('idna'), flags)
File "C:\Program Files\Python37\lib\site-packages\whois\whois.py", line 264, in whois_lookup
result = self.whois(query_arg, nichost, flags)
File "C:\Program Files\Python37\lib\site-packages\whois\whois.py", line 142, in whois
s.connect((hostname, 43))
socket.timeout: timed out
Your code has at least two problems, and you may have a network problem also.
However, there is no reason for it not to work on Python2.
About the code
This works perfectly fine:
In [7]: import whois
In [8]: print whois.query('stackoverflow.com').expiration_date
2020-02-02 11:59:59
Note two things:
whois is about domain names, not URLs; so you should pass a domain name; note more generally that for new endeavors you should have a look at RDAP instead of whois since you will get a far better experience
you need to use whois.query not whois.whois (you are not saying which version of the library you use, but at its documentation page on https://pypi.org/project/whois/ you can clearly see it is whois.query so I do not know where your whois.whois` comes from).
About the network
You show a network error. It is not 100% clear but you may or may not have access to the whois servers you want to query.
Easy way to test: just use the command line whois from the same box as your code (but again use a domain name, not a URL as parameter) and you will see what is happening.
You can even do directly a telnet on port 43 as whois does nothing else.
$ echo 'stackoverflow.com' | nc whois.verisign-grs.com 43 | grep 'Expiry'
Registry Expiry Date: 2020-02-02T11:59:59Z
I've created a standalone exe Windows service written in Python and built with pyInstaller. When I try to import wmi, an exception is thrown.
What's really baffling is that I can do it without a problem if running the code in a foreground exe, or a foreground python script, or a python script running as a background service via pythonservice.exe!
Why does it fail under this special circumstance of running as a service exe?
import wmi
Produces this error for me:
com_error: (-2147221020, 'Invalid syntax', None, None)
Here's the traceback:
Traceback (most recent call last):
File "<string>", line 43, in onRequest
File "C:\XXX\XXX\XXX.pyz", line 98, in XXX
File "C:\XXX\XXX\XXX.pyz", line 31, in XXX
File "C:\XXX\XXX\XXX.pyz", line 24, in XXX
File "C:\XXX\XXX\XXX.pyz", line 34, in XXX
File "C:\Program Files (x86)\PyInstaller-2.1\PyInstaller\loader\pyi_importers.py", line 270, in load_module
File "C:\XXX\XXX\out00-PYZ.pyz\wmi", line 157, in <module>
File "C:\XXX\XXX\out00-PYZ.pyz\win32com.client", line 72, in GetObject
File "C:\XXX\XXX\out00-PYZ.pyz\win32com.client", line 87, in Moniker
wmi.py line 157 has a global call to GetObject:
obj = GetObject ("winmgmts:")
win32com\client__init.py__ contains GetObject(), which ends up calling Moniker():
def GetObject(Pathname = None, Class = None, clsctx = None):
"""
Mimic VB's GetObject() function.
ob = GetObject(Class = "ProgID") or GetObject(Class = clsid) will
connect to an already running instance of the COM object.
ob = GetObject(r"c:\blah\blah\foo.xls") (aka the COM moniker syntax)
will return a ready to use Python wrapping of the required COM object.
Note: You must specifiy one or the other of these arguments. I know
this isn't pretty, but it is what VB does. Blech. If you don't
I'll throw ValueError at you. :)
This will most likely throw pythoncom.com_error if anything fails.
"""
if clsctx is None:
clsctx = pythoncom.CLSCTX_ALL
if (Pathname is None and Class is None) or \
(Pathname is not None and Class is not None):
raise ValueError("You must specify a value for Pathname or Class, but not both.")
if Class is not None:
return GetActiveObject(Class, clsctx)
else:
return Moniker(Pathname, clsctx)
The first line in Moniker(), i.e. MkParseDisplayName() is where the exception is encountered:
def Moniker(Pathname, clsctx = pythoncom.CLSCTX_ALL):
"""
Python friendly version of GetObject's moniker functionality.
"""
moniker, i, bindCtx = pythoncom.MkParseDisplayName(Pathname)
dispatch = moniker.BindToObject(bindCtx, None, pythoncom.IID_IDispatch)
return __WrapDispatch(dispatch, Pathname, clsctx=clsctx)
Note: I tried using
pythoncom.CoInitialize()
which apparently solves this import problem within a thread, but that didn't work...
I also face the same issue and I figure out this issue finally,
import pythoncom and CoInitialize pythoncom.CoInitialize (). They import wmi
import pythoncom
pythoncom.CoInitialize ()
import wmi
I tried solving this countless ways. In the end, I threw in the towel and had to just find a different means of achieving the same goals I had with wmi.
Apparently that invalid syntax error is thrown when trying to create an object with an invalid "moniker name", which can simply mean the service, application, etc. doesn't exist on the system. Under this circumstance "winmgmts" just can't be found at all it seems! And yes, I tried numerous variations on that moniker with additional specs, and I tried running the service under a different user account, etc.
Honestly I didn't dig in order to understand why this occurs.
Anyway, the below imports solved my problem - which was occurring only when ran from a Flask instance:
import os
import pythoncom
pythoncom.CoInitialize()
from win32com.client import GetObject
import wmi
The error "com_error: (-2147221020, 'Invalid syntax', None, None)" is exactly what popped up in my case so I came here after a long time of searching the web and voila:
Under this circumstance "winmgmts" just can't be found at all it
seems!
This was the correct hint for because i had just a typo , used "winmgmt:" without trailing 's'. So invalid sythax refers to the first methods parameter, not the python code itself. o_0 Unfortunately I can't find any reference which objects we can get with win32com.client.GetObject()... So if anybody has a hint to which params are "allowed" / should work, please port it here. :-)
kind regards
ChrisPHL
I want to make an script in python that reads mails from Lotus Notes 8.5 and then create for each email an issue in jira but it returns me this error when I try to read the mails from Lotus:
Traceback (most recent call last):
File "from_Lotus_TO_Jira.py", line 46, in <module>
main()
File "from_Lotus_TO_Jira.py", line 39, in main
folder = notesDatabase.GetView('$Inbox')
File "C:\Python27\lib\site-packages\win32com\gen_py\29131520-2EED-1069-BF5D-00
DD011186B7x0x1x2.py", line 1849, in GetView
ret = self._oleobj_.InvokeTypes(1610743866, LCID, 1, (9, 0), ((8, 1),),pName
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, u'NotesDatabase',
u'Database server_name!!C:\\Users\\MYNAME\\AppData\\Local\\Lotus\\Notes\\Data\\ma
il202\\myname.nsf has not been opened yet', None, 0, -2147217441), None)
here is my .py file
import win32com.client
import pywintypes
import getpass
def main():
# Get credentials
mailServer = 'server_name'
mailPath = 'C:\Users\MYNAME\AppData\Local\Lotus\Notes\Data\mail202\myname.nsf'
mailPassword = ''
# Connect
notesSession = win32com.client.Dispatch('Lotus.NotesSession')
notesSession.Initialize(mailPassword)
notesDatabase = notesSession.GetDatabase(mailServer, mailPath)
# Get a list of folders
folder = notesDatabase.GetView('$Inbox')
document = folder.GetFirstDocument()
if __name__ == "__main__":
main()
Looking at http://www-01.ibm.com/support/docview.wss?uid=swg21308538
The full filepath (e.g. "C:\notes\data\r_apps\haha.nsf") may
optionally be used when accessing local databases on a workstation. If
you specify a server name, however, or if the code is running on a
server, you must use the path relative to the Notes data directory
("r_apps\haha.nsf").
I suggest either (a) not specifying a server or (b) only giving a relative path, ie mailPath = r'mail202\myname.nsf'.
You are using the Notes COM classes. There is a nice shortcut call for opening the current user's mail database. The NotesSession class contains a GetDbDirectory method, which returns a NotesDbDirectory object, and the NotesDbDirectory class contains an OpenMailDatabase method.
I'm not a Python guy so I can't vouch for the exact syntax, but it should be along the lines of this:
notesSession.Initialize(mailPassword)
notesDbDirectory = notesSession.GetDbDirectory('')
notesDatabase = NotesDbDirectory.GetMailDatabase()
Note that the argument to GetDbDirectory can be an empty string or the name of a Domino server. It should not make any difference, as the GetMailDatabase method follows the same procedure as the NotesDatabase.OpenMail method (which is not exposed via the COM interface, therefore it is unavailable to Python). I.e., it looks at the current user's Notes client configuration to locate either a server-based or local replica of the user's mail database.
Also note that if this code is intended to run on one machine but process mail for many users on one Domino server, then you can't use the GetMailDatabase method. In that case, using the relative path as in #Hugh-Bothwell's answer would be correct, although I would strongly recommend adding some defensive programming via a call to notesDatabase.IsOpen() in between the calls to the GetDatabase() and GetView().
Hi I am currently learning PyEZ to configure JunOS devices from Python. But I am stuck at a certain problem. I want to be able to create new users through Python but I can't figure out how to enter passwords with python. I have tried many different things but can't seem to make it work. Any advice would be appriciated
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
dev = Device(host='192.168.56.2', user='root', password='Juniper1')
dev.open()
cu=Config(dev)
new_User='set system login user Read class read-only authentication plain-text-password'
pass_New='Read1234'
pass_Repeat='Read1234'
cu.load(new_User, format='set')
cu.load(pass_New,format='set')
cu.load(pass_Repeat,format='set')
And Here is the Error
Traceback (most recent call last):
File "/home/oscar/PycharmProjects/Junos/HelloWorld.py", line 18, in <module>
cu.load(pass_New,format='set')
File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/utils/config.py", line 377, in load
return try_load(rpc_contents, rpc_xattrs)
File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/utils/config.py", line 343, in try_load
raise ConfigLoadError(cmd=err.cmd, rsp=err.rsp, errs=err.errs)
jnpr.junos.exception.ConfigLoadError: ConfigLoadError(severity: error, bad_element: Read1234, message: unknown command)
When you're using PyEZ to apply configuration, the module is expecting atomic configuration blobs; it is not just a replacement for the interactive CLI shell.
The error you are seeing is because you're sending pass_New 'Read1234' when Junos is expecting a specific set command.
To achieve your goal, you'll have to provide the hashed version of the password in your code, and send that as part of the new_User command.
To do this you'll need a hashing module - I use passlib, because crypt() function in OSX spits out hashes that are not compatible with Junos even though they are both BSD variants - go figure.
#!/usr/bin/python
from passlib.hash import md5_crypt
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
username = 'Read'
plaintext = 'toomanysecrets'
dev = Device(host='192.168.56.2', user='root',passwd='Juniper1')
dev.open()
cu=Config(dev)
hashedpassword = md5_crypt.encrypt(plaintext)
set_command = 'set system login user '+username+' class read-only authentication encrypted-password '+hashedpassword
cu.load(set_command, format='set')
dev.commit()
dev.close()
Also to add why we can't do
new_User='set system login user Read class read-only authentication plain-text-password'
pass_New='Read1234'
pass_Repeat='Read1234'
cu.load(new_User, format='set')
cu.load(pass_New,format='set')
cu.load(pass_Repeat,format='set')
I can notice you are trying to type/retupe password using load which is not how load function works. PyEZ in background work on netconf, it's not a screen scrapping. Hence we should not try simulating that.
When we call load it tries to load the config via load-configuration rpc.
I tried looking at the documentation for running ZEO on a ZODB database, but it isn't working how they say it should.
I can get a regular ZODB running fine, but I would like to make the database accessible by several processes for a program, so I am trying to get ZEO to work.
I created this script in a folder with a subfolder zeo, which will hold the "database.fs" files created by the make_server function in a different parallel process:
CODE:
from ZEO import ClientStorage
import ZODB
import ZODB.config
import os, time, site, subprocess, multiprocessing
# make the server in for the database in a separate process with windows command
def make_server():
runzeo_path = site.getsitepackages()[0] + "\Lib\site-packages\zeo-4.0.0-py2.7.egg\ZEO\\runzeo.py"
filestorage_path = os.getcwd() + '\zeo\database.fs'
subprocess.call(["python", runzeo_path, "-a", "127.0.0.1:9100", "-f" , filestorage_path])
if __name__ == "__main__":
server_process = multiprocessing.Process(target = make_server)
server_process.start()
time.sleep(5)
storage = ClientStorage.ClientStorage(('localhost', 9100), wait=False)
db = ZODB.DB(storage)
connection = db.open()
root = connection.root()
the program will just block at the ClientStorage line if the wait=False is not given.
If the wait=False is given it produces this error:
Error Message:
Traceback (most recent call last):
File "C:\Users\cbrown\Google Drive\EclipseWorkspace\NewSpectro - v1\20131202\2 - database\zeo.py", line 17, in <module>
db = ZODB.DB(storage)
File "C:\Python27\lib\site-packages\zodb-4.0.0-py2.7.egg\ZODB\DB.py", line 443, in __init__
temp_storage.load(z64, '')
File "C:\Python27\lib\site-packages\zeo-4.0.0-py2.7.egg\ZEO\ClientStorage.py", line 841, in load
data, tid = self._server.loadEx(oid)
File "C:\Python27\lib\site-packages\zeo-4.0.0-py2.7.egg\ZEO\ClientStorage.py", line 88, in __getattr__
raise ClientDisconnected()
ClientDisconnected
Here is the output from the cmd prompt for my process which runs a server:
------
2013-12-06T21:07:27 INFO ZEO.runzeo (7460) opening storage '1' using FileStorage
------
2013-12-06T21:07:27 WARNING ZODB.FileStorage Ignoring index for C:\Users\cab0008
\Google Drive\EclipseWorkspace\NewSpectro - v1\20131202\2 - database\zeo\databas
e.fs
------
2013-12-06T21:07:27 INFO ZEO.StorageServer StorageServer created RW with storage
s: 1:RW:C:\Users\cab0008\Google Drive\EclipseWorkspace\NewSpectro - v1\20131202\
2 - database\zeo\database.fs
------
2013-12-06T21:07:27 INFO ZEO.zrpc (7460) listening on ('127.0.0.1', 9100)
What could I be doing wrong? I just want this to work locally right now so there shouldn't be any need for fancy web stuff.
You should use proper process management and simplify your life. You likely want to look into supervisor, which can be responsible for running/starting/stopping your application and ZEO.
Otherwise, you need to look at the double-fork trick to daemonize ZEO -- but why bother when a process management tool like supervisor does this for you.
If you are savvy with relational database administration, and already have a relational database at your disposal -- you can also consider RelStorage as a very good ZODB (low-level) storage backend.
In Windows you should use double \ instead of a single \ in the paths. Easy and portable way to accomplish this is to use os.path.join() function, eg. os.path.join('os.getcwd()', 'zeo', 'database.fs'). Otherwise a similar code worked ok for me.
Had same error on Windows , on Linux everything OK ...
your code is ok , to make this to work change following
C:\Python33\Lib\site-packages\ZEO-4.0.0-py3.3.egg\ZEO\zrpc\trigger.py ln:235
self.trigger.send(b'x')
C:\Python33\Lib\site-packages\ZEO-4.0.0-py3.3.egg\ZEO\zrpc\client.py ln:458:459 - comment them
here is those lines:
if socktype != socket.SOCK_STREAM:
continue