def test_get_new_events_with_fallback(realtime_instance): realtime_instance['use_collect_events_fallback'] = True with patch('datadog_checks.vsphere.api.connect'): config = VSphereConfig(realtime_instance, MagicMock()) api = VSphereAPI(config, MagicMock()) event1 = vim.event.Event(key=1) event3 = vim.event.Event(key=3) event_collector = MagicMock() api._conn.content.eventManager.QueryEvents.side_effect = [ SoapAdapter.ParserError("some parse error"), [event1], SoapAdapter.ParserError("event parse error"), [event3], ] api._conn.content.eventManager.CreateCollectorForEvents.return_value = event_collector event_collector.ReadNextEvents.side_effect = [ [event1], SoapAdapter.ParserError("event parse error"), [event3], [], ] events = api.get_new_events(start_time=dt.datetime.now()) assert events == [event1, event3]
def _copyHostProfile(self, hostProfile): """Helper function that makes a copy of the host profile document. """ # TBD: Is there a better way than serializing/deserializing? serializedProf = SoapAdapter.Serialize( hostProfile, version=newestVersions.get('vim')) deserializedProf = SoapAdapter.Deserialize(serializedProf) return deserializedProf
def test_serialize_unicode(self): self.assertEqual( SoapAdapter.SerializeToUnicode('Ḃ'), u'<object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:vim25" xsi:type="xsd:string">\u1e02</object>' ) self.assertEqual( SoapAdapter.SerializeToUnicode(u'Ḃ'), u'<object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:vim25" xsi:type="xsd:string">\u1e02</object>' ) self.assertEqual( SoapAdapter.SerializeToUnicode(u'\u1e02'), u'<object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:vim25" xsi:type="xsd:string">\u1e02</object>' )
def InvokeMethod(self, mo, info, args): req = self.SerializeRequest(mo, info, args) scgireq = ScgiRequest( { 'REQUEST_METHOD': 'POST', 'HTTP_SOAPACTION': self.versionId[1:-1] }, message=req) scgireq.Write(self.p.stdin) self.p.stdin.flush() try: outText = ReadNetString(self.p.stdout) except Scgi_EOF: errText = "Unexpected EOF reading from process, maybe process died" raise self.systemError(msg=errText, reason=errText) except Exception as e: errText = "Error parsing output from SCGI process: %s" % (e) raise self.systemError(msg=errText, reason=errText) (responseHeaders, responseBody) = SoapAdapter.ParseHttpResponse(outText) # Parse status code from response headers [Status: 200 OK] error = False obj = None statusmatch = re.search(r'Status:\s+(\d+)\s+(.+)', responseHeaders) if not statusmatch: errText = "Could not find SOAP status in SOAP headers (%s)" % ( responseHeaders) raise self.systemError(msg=errText, reason=errText) elif statusmatch.group(1) != '200': errText = statusmatch.group(2).rstrip() error = True # SoapResponseDeserializer can only handle XML if 'text/xml' in responseHeaders: try: obj = SoapAdapter.SoapResponseDeserializer(self).Deserialize( responseBody, info.result) except: errText = "Failure parsing SOAP response (%s)" % (outText) raise self.systemError(msg=errText, reason=errText) if not error: return obj elif obj is None: raise self.systemError(msg=errText, reason=responseBody) else: raise obj
def __init__(self, cmd, version='vim.version.version9'): SoapAdapter.SoapStubAdapterBase.__init__(self, version=version) self.cmd = cmd self.systemError = SoapAdapter.GetVmodlType('vmodl.fault.SystemError') argv = self.cmd.split() self.p = subprocess.Popen(argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
def deserialize(clazz, data): if clazz is None: return SoapAdapter.Deserialize(data) if data else None elif clazz is list: return [deserialize(*elem) for elem in data] #elif issubclass(clazz, (VsphereObject, VsphereData, dict)): else: return clazz(**{k: deserialize(*v) for k, v in data.items()})
def test_get_new_events_failure_without_fallback(realtime_instance): with patch('datadog_checks.vsphere.api.connect'): config = VSphereConfig(realtime_instance, MagicMock()) api = VSphereAPI(config, MagicMock()) api._conn.content.eventManager.QueryEvents.side_effect = SoapAdapter.ParserError("some parse error") with pytest.raises(SoapAdapter.ParserError): api.get_new_events(start_time=dt.datetime.now())
def setUp(self): self.version = newestVersions.get('vim') self.versionUri = VmomiSupport.GetVersionNamespace(self.version) self.futureVersionUri = "vim25/foo" self.badVersionUri = "notvim/foo" self.stub = SoapAdapter.SoapStubAdapter(version=self.version) self.deserializer = SoapAdapter.SoapResponseDeserializer(self.stub) self.soapHeaderBegin = \ """<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body>""" self.soapHeaderEnd = \ """</soapenv:Body> </soapenv:Envelope>""" ImportTypesAndManagedObjects()
def __init__(self, version=newestVersions.get('vim'), printRequest=False, printResponse=False): SoapAdapter.SoapStubAdapter.__init__(self, version=version) self.ns = VmomiSupport.GetVersionNamespace(version) self.soapHandler = SoapHandler.SoapHandler() self.soapDeserializer = SoapAdapter.SoapResponseDeserializer(self) self.printRequest = printRequest self.printResponse = printResponse ImportTypesAndManagedObjects()
def WriteXml(self, obj, file=None): file = file or self.wfile self.send_header('Content-type', 'text/xml') self.end_headers() xmlStr = SoapAdapter.Serialize(obj) tag = "MobData" xmlDoc = '<?xml version="1.0" encoding="UTF-8"?>' \ '<%s xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' \ 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' \ '%s</%s>' % (tag, xmlStr, tag) file.write(xmlDoc)
def serialize(obj): obj_cls = obj.__class__ if obj_cls is dict: res = {k: serialize(v) for k, v in obj.items()} elif obj_cls is list: res = [serialize(val) for val in obj] elif issubclass(obj_cls, (VsphereObject, VsphereData)): res = { k: serialize(v) for k, v in obj.__dict__.items() if not k.startswith('_') } else: try: res = SoapAdapter.Serialize(obj) except UnicodeEncodeError: print("WARNING: Failed to serialize %s data" % type(obj)) return None, None obj_cls = None return obj_cls, res
def test_serialize_float(self): pc = vim.host.VsanInternalSystem.PolicyCost() pc.diskSpaceToAddressSpaceRatio = 1.0 SoapAdapter.Serialize(pc, version='vim.version.version10')
def test_serialize_integer(self): lp = vim.LongPolicy() lp.inherited = False lp.value = 100 SoapAdapter.Serialize(lp, version='vim.version.version10')
def test_serialize_object(self): val = vim.vm.device.VirtualDeviceSpec.FileOperation() # This line should not raise an exception, especially on Python 3. SoapAdapter.Serialize(val)
def Login(self): """ Session login """ if self._stub: return host = self.options.server protocol = self.options.protocol try: port = int(self.options.portnumber) except ValueError: message = "Invalid port number %s" % self.options.portnumber raise SessionArgumentException(message) path = self.options.servicepath user = self.options.username password = self.options.password url = self.options.url sessionFile = self.options.sessionfile saveSessionFile = self.options.savesessionfile if self.options.encoding: encoding = self._VerifyEncoding(self.options.encoding) if encoding: self.options.encoding = encoding else: message = "Unknown encoding %s" % self.options.encoding raise SessionArgumentException(message) # Using version8 to connect since LoginByToken was introduced then version = 'vim.version.version9' passthroughAuth = self.options.passthroughauth passthroughAuthPackage = self.options.passthroughauthpackage credStorePath = self.options.credstore try: if credStorePath is None or len(credStorePath.strip()) == 0: # Will throw if HOME not set credStorePath = GetViSdkCredPlatformPath(sys.platform) except KeyError: pass credStore = self._GetCredstoreFromPath(credStorePath) # Url override if url: host, port, protocol, path = self._ParseURL(url=url) # Session file override cookie = None if sessionFile: host, cookie = self._GetCookieFromFile(host, sessionFile) # Lookup Service URL psc = self.options.psc lsUrl = None if psc: lsUrl = "https://" + psc + "/lookupservice/sdk" # If not in visor, then host should already be set or --psc specified. if not host and not lsUrl: if IsInVisor(): host = "localhost" else: message = "Must specify a server name" raise SessionArgumentException(message) # Local host useLocalLogin = False if IsInVisor() and host in ("localhost", "127.0.0.1", "::1") and \ password is None: # Use local login for VMkernel useLocalLogin = True # Do not use SSL protocol = "http" port = 80 cacertsFile = self.options.cacertsfile thumbprint = None if not useLocalLogin and not cacertsFile: # We need a thumbprint. thumbprint = self.options.thumbprint if not thumbprint and credStore: thumbprint = credStore.GetThumbprint(host) if not thumbprint: # Not found on command line or credstore. # Make up one, so that the check fails. Collision is impossible due to # the symbol K, which will never appear in a server thumbprint. thumbprint = "FA:KE:FA:KE:FA:KE:FA:KE:FA:KE:FA:KE:FA:KE:FA:KE:FA:KE:FA:KE" stsUrl = None stsThumbprint = None vcThumbprint = None # Check protocol # Negative port indicate http if protocol == "http": if port > 0: port = -port elif protocol == "https": if port < 0: port = -port else: message = "Unsupported protocol %s" % protocol raise SessionArgumentException(message) MAX_RETRY_SECONDS = 100 connectStartTime = time.time() connected = False while not connected: localTicket = None try: # Look up VC URL only if none of --server and --url options are set. if not stsUrl and lsUrl and not host and not url: # TODO: In the future we may prompt the user to make a choice # if more than one VCs are registered with Lookup Service. # Until then we use the first VC URL that we find. url, vcThumbprint = self._GetVcUrlFromLookupService( lsUrl, cacertsFile=cacertsFile, thumbprint=thumbprint) logging.info("Got VC URL from PSC: " + url) host, port, protocol, path = self._ParseURL(url=url) # TODO: In the future we may prompt the user to make a choice if # more than one SSO servers are registered with Lookup Service. # Until then we use the first STS URL that we find. stsUrl, stsThumbprint = self._GetStsUrlFromLookupService( lsUrl, cacertsFile=cacertsFile, thumbprint=thumbprint) logging.info("Got STS URL from PSC: " + stsUrl) # We'll verify vCenter Server certificate by vcThumbprint # and SSO server certificate by stsThumbprint, so we don't need # cacertsFile any more. thumbprint = vcThumbprint cacertsFile = None # Create Soap stub reqLogin = True context = CreateSslContext(cacertsFile, thumbprint) stub = SoapAdapter.SoapStubAdapter(host=host, port=port, version=version, path=path, thumbprint=thumbprint, sslContext=context) if sessionFile: # Use session file if cookie: stub.cookie = cookie.name + "=" + cookie.value + ";" + \ " Path=" + cookie.path + ";" reqLogin = False elif passthroughAuth: # Do authentication below pass elif useLocalLogin: if not user: user = GetSessionUserName() elif password is None and credStore: # Try to use credential store if no password is given. # If user is not specified and there is only 1 user in cred store, # then take the user and password from credstore if not user: try: users = credStore.GetUserNames(host) except Exception as err: errMsg = "Credential store file %s is corrupted" % credStorePath logging.error(errMsg) error = err raise IOError(errMsg) if len(users) == 1: logging.info("Using user: %s" % users[0]) user = users[0] if not user: user = userInput("Enter username: "******"Credential store file %s is corrupted" % credStorePath logging.error(errMsg) error = err raise IOError(errMsg) logging.info("Connecting to " + host + "@" + str(port)) content = self._GetServiceContent(stub) sessionMgr = content.sessionManager if reqLogin: # Ask for user / password if not given if not passthroughAuth: if not user: user = userInput("Enter username: "******"Enter password: "******"" try: localTicketPasswd = open(localTicket.passwordFilePath).read() except IOError as err: LogException(err) logging.error("Failed to read local ticket") error = err userSession = sessionMgr.Login(localTicket.userName, localTicketPasswd) else: userSession = sessionMgr.Login(user, password, None) if not userSession: raise SessionException("Invalid login") # Do we need to logout? reqLogout = reqLogin if saveSessionFile: reqLogout = False logging.info("Connected") connected = True self._host = host self._stub = stub self._content = content self._sessionMgr = sessionMgr self._reqLogout = reqLogout except vim.fault.InvalidLogin as err: exitMessage = "Invalid login: {0}".format(err.msg) timeDelta = time.time() - connectStartTime if localTicket is not None and timeDelta < MAX_RETRY_SECONDS: # The local ticket may have expired due to its short life time # of 10 seconds. Try again. # SessionManager.login() API has a dealy of ~4 sec. logging.error(exitMessage) logging.error("Will retry login in 1 second") error = None continue LogException(err) raise SessionLoginException(err, message=exitMessage) except vmodl.MethodFault as err: exitMessage = "Error: {0}.".format(err.msg) LogException(err) raise SessionLoginException(err, message=exitMessage) except ssl.CertificateError as err: exitMessage = "Certificate error: {0}".format(err) LogException(err) raise SessionLoginException(err, message=exitMessage) except ssl.SSLError as err: # Special handling for SSL error. Need to put before IOError, as # ssl.SSLError subclass IOError exitMessage = "SSL error 0x{0:x}".format(err.errno) LogException(err) raise SessionLoginException(err, message=exitMessage) except IOError as err: exitMessage = "IO error: {0}".format(str(err)) LogException(err) raise SessionLoginException(err, message=exitMessage) except ThumbprintMismatchException as err: expected = ':'.join(re.findall(r'(..)', err.expected.upper())) actual = ':'.join(re.findall(r'(..)', err.actual.upper())) exitMessage = "Certificate error. Server SHA-1 thumbprint: {0}".format( actual) if expected.find('FA:KE') == -1: exitMessage = "{0} (expected: {1})".format(exitMessage, expected) else: exitMessage = "{0} (not trusted)".format(exitMessage) # Don't log the fake thumbprint. exitMessage is fine. LogException(err) raise SessionLoginException(err, message=exitMessage) except SessionException as err: LogException(err) raise except Exception as err: exitMessage = "Connection failed" LogException(err) raise SessionLoginException(err, message=exitMessage)