Esempio n. 1
0
    def connect(self,
                host,
                user,
                password,
                trace_file=None,
                sock_timeout=None):
        """Opens a session to a VC/ESX server with the given credentials:
        @host: is the server's hostname or address. If the web service uses
        another protocol or port than the default, you must use the full
        service URL (e.g. http://myhost:8888/sdk)
        @user: username to connect with
        @password: password to authenticate the session
        @trace_file: (optional) a file path to log SOAP requests and responses
        @sock_timeout: (optional) only for python >= 2.6, sets the connection
        timeout for sockets, in python 2.5 you'll  have to use
        socket.setdefaulttimeout(secs) to change the global setting.
        """

        self.__user = user
        self.__password = password
        #Generate server's URL
        if not isinstance(host, basestring):
            raise VIException("'host' should be a string with the ESX/VC url.",
                              FaultTypes.PARAMETER_ERROR)

        elif (host.lower().startswith('http://')
              or host.lower().startswith('https://')):
            server_url = host.lower()

        else:
            server_url = 'https://%s/sdk' % host

        try:
            #get the server's proxy
            locator = VI.VimServiceLocator()
            args = {'url': server_url}
            if trace_file:
                trace = open(trace_file, 'w')
                args['tracefile'] = trace
            if sock_timeout and sys.version_info >= (2, 6):
                args['transdict'] = {'timeout': sock_timeout}

            self._proxy = locator.getVimPortType(**args)

            for header, value in self.__initial_headers.iteritems():
                self._proxy.binding.AddHeader(header, value)

            #get service content from service instance
            request = VI.RetrieveServiceContentRequestMsg()
            mor_service_instance = request.new__this('ServiceInstance')
            mor_service_instance.set_attribute_type(MORTypes.ServiceInstance)
            request.set_element__this(mor_service_instance)
            self._do_service_content = self._proxy.RetrieveServiceContent(
                request)._returnval
            self.__server_type = self._do_service_content.About.Name
            self.__api_version = self._do_service_content.About.ApiVersion
            self.__api_type = self._do_service_content.About.ApiType

            #login
            request = VI.LoginRequestMsg()
            mor_session_manager = request.new__this(
                self._do_service_content.SessionManager)
            mor_session_manager.set_attribute_type(MORTypes.SessionManager)
            request.set_element__this(mor_session_manager)
            request.set_element_userName(user)
            request.set_element_password(password)
            self.__session = self._proxy.Login(request)._returnval
            self.__logged = True

        except (VI.ZSI.FaultException), e:
            raise VIApiException(e)
Esempio n. 2
0
    def connect(self, host, user=None, password=None, passthrough=False, trace_file=None, sock_timeout=None):
        """Opens a session to a VC/ESX server with the given credentials:
        @host: is the server's hostname or address. If the web service uses
        another protocol or port than the default, you must use the full
        service URL (e.g. http://myhost:8888/sdk)
        @user: (optional) username to connect with
        @password: (optional) password to authenticate the session
        @passthrough: (optional) use Windows session credentials
        or MIT Kerberos credentials to connect.
        User should provide user/password pair OR set passthrough to True
        @trace_file: (optional) a file path to log SOAP requests and responses
        @sock_timeout: (optional) only for python >= 2.6, sets the connection
        timeout for sockets, in python 2.5 you'll  have to use
        socket.setdefaulttimeout(secs) to change the global setting.
        """
        if (((user is None or password is None) and not passthrough)
        or ((user is not None or password is not None) and passthrough)):
            raise TypeError("connect() takes user/password pair OR passthrough=True")

        self.__user = user
        self.__password = password
        #Generate server's URL
        if not isinstance(host, basestring):
            raise VIException("'host' should be a string with the ESX/VC url."
                             ,FaultTypes.PARAMETER_ERROR)

        elif (host.lower().startswith('http://')
        or host.lower().startswith('https://')):
            server_url = host.lower()

        else:
            server_url = 'https://%s/sdk' % host

        try:
            #get the server's proxy
            locator = VI.VimServiceLocator()
            args = {'url':server_url}
            if trace_file:
                trace=open(trace_file, 'w')
                args['tracefile'] = trace
            if sock_timeout and sys.version_info >= (2, 6):
                args['transdict'] = {'timeout':sock_timeout}

            self._proxy = locator.getVimPortType(**args)

            for header, value in self.__initial_headers.iteritems():
                self._proxy.binding.AddHeader(header, value)

            #get service content from service instance
            request = VI.RetrieveServiceContentRequestMsg()
            mor_service_instance = request.new__this('ServiceInstance')
            mor_service_instance.set_attribute_type(MORTypes.ServiceInstance)
            request.set_element__this(mor_service_instance)
            self._do_service_content = self._proxy.RetrieveServiceContent(
                                                             request)._returnval
            self.__server_type = self._do_service_content.About.Name
            self.__api_version = self._do_service_content.About.ApiVersion
            self.__api_type = self._do_service_content.About.ApiType

            if not passthrough:
                #login with user/password
                request = VI.LoginRequestMsg()
                mor_session_manager = request.new__this(
                                            self._do_service_content.SessionManager)
                mor_session_manager.set_attribute_type(MORTypes.SessionManager)
                request.set_element__this(mor_session_manager)
                request.set_element_userName(user)
                request.set_element_password(password)
                self.__session = self._proxy.Login(request)._returnval
                self.__logged = True

            else:
                fqdn, aliases, addrs = gethostbyaddr(urlparse(server_url).netloc)
                if os.name == 'nt':
                    #login with Windows session credentials
                    try:
                        from sspi import ClientAuth
                    except ImportError:
                        raise ImportError("To enable passthrough authentication please"\
                            " install pywin32 (available for Windows only)")
                    spn = "host/%s" % fqdn
                    client = ClientAuth("Kerberos", targetspn=spn)

                    def get_token(serverToken=None):
                        if serverToken is not None:
                            serverToken = b64decode(serverToken)
                        err, bufs = client.authorize(serverToken)
                        return b64encode(bufs[0].Buffer)
                else:
                    #login with MIT Kerberos credentials
                    try:
                        import kerberos
                    except ImportError:
                        raise ImportError("To enable passthrough authentication please"\
                            " install python bindings for kerberos")
                    spn = "host@%s" % fqdn
                    flags = kerberos.GSS_C_INTEG_FLAG|kerberos.GSS_C_SEQUENCE_FLAG|\
                        kerberos.GSS_C_REPLAY_FLAG|kerberos.GSS_C_CONF_FLAG
                    errc, client = kerberos.authGSSClientInit(spn, gssflags=flags)

                    def get_token(serverToken=''):
                        cres = kerberos.authGSSClientStep(client, serverToken)
                        return kerberos.authGSSClientResponse(client)

                token = get_token()

                while not self.__logged:
                    try:
                        request = VI.LoginBySSPIRequestMsg()
                        mor_session_manager = request.new__this(
                                                    self._do_service_content.SessionManager)
                        mor_session_manager.set_attribute_type(MORTypes.SessionManager)
                        request.set_element__this(mor_session_manager)
                        request.set_element_base64Token(token)
                        self.__session = self._proxy.LoginBySSPI(request)._returnval
                        self.__logged = True
                    except (VI.ZSI.FaultException), e:
                        if e.fault.string == "fault.SSPIChallenge.summary":
                            serverToken = e.fault.detail[0].Base64Token
                            token = get_token(serverToken)
                        else:
                            raise e

        except (VI.ZSI.FaultException), e:
            raise VIApiException(e)