def __init__( self, endpoint, uuid, username, password, cacert=None, macaroons=None, loop=None): self.endpoint = endpoint self.uuid = uuid if macaroons: self.macaroons = macaroons self.username = '' self.password = '' else: self.macaroons = [] self.username = username self.password = password self.cacert = cacert self.loop = loop or asyncio.get_event_loop() self.__request_id__ = 0 self.addr = None self.ws = None self.facades = {} self.messages = IdQueue(loop=self.loop) self.monitor = Monitor(connection=self)
async def connect( cls, endpoint=None, uuid=None, username=None, password=None, cacert=None, bakery_client=None, loop=None, max_frame_size=None, ): """Connect to the websocket. If uuid is None, the connection will be to the controller. Otherwise it will be to the model. :param str endpoint: The hostname:port of the controller to connect to. :param str uuid: The model UUID to connect to (None for a controller-only connection). :param str username: The username for controller-local users (or None to use macaroon-based login.) :param str password: The password for controller-local users. :param str cacert: The CA certificate of the controller (PEM formatted). :param httpbakery.Client bakery_client: The macaroon bakery client to to use when performing macaroon-based login. Macaroon tokens acquired when logging will be saved to bakery_client.cookies. If this is None, a default bakery_client will be used. :param asyncio.BaseEventLoop loop: The event loop to use for async operations. :param int max_frame_size: The maximum websocket frame size to allow. """ self = cls() if endpoint is None: raise ValueError('no endpoint provided') self.uuid = uuid if bakery_client is None: bakery_client = httpbakery.Client() self.bakery_client = bakery_client if username and '@' in username and not username.endswith('@local'): # We're trying to log in as an external user - we need to use # macaroon authentication with no username or password. if password is not None: raise errors.JujuAuthError('cannot log in as external ' 'user with a password') username = None self.usertag = tag.user(username) self.password = password self.loop = loop or asyncio.get_event_loop() self.__request_id__ = 0 # The following instance variables are initialized by the # _connect_with_redirect method, but create them here # as a reminder that they will exist. self.addr = None self.ws = None self.endpoint = None self.cacert = None self.info = None # Create that _Task objects but don't start the tasks yet. self._pinger_task = _Task(self._pinger, self.loop) self._receiver_task = _Task(self._receiver, self.loop) self.facades = {} self.messages = IdQueue(loop=self.loop) self.monitor = Monitor(connection=self) if max_frame_size is None: max_frame_size = self.MAX_FRAME_SIZE self.max_frame_size = max_frame_size await self._connect_with_redirect([(endpoint, cacert)]) return self
async def connect( cls, endpoint=None, uuid=None, username=None, password=None, cacert=None, bakery_client=None, loop=None, max_frame_size=None, retries=3, retry_backoff=10, specified_facades=None, ): """Connect to the websocket. If uuid is None, the connection will be to the controller. Otherwise it will be to the model. :param str endpoint: The hostname:port of the controller to connect to (or list of strings). :param str uuid: The model UUID to connect to (None for a controller-only connection). :param str username: The username for controller-local users (or None to use macaroon-based login.) :param str password: The password for controller-local users. :param str cacert: The CA certificate of the controller (PEM formatted). :param httpbakery.Client bakery_client: The macaroon bakery client to to use when performing macaroon-based login. Macaroon tokens acquired when logging will be saved to bakery_client.cookies. If this is None, a default bakery_client will be used. :param asyncio.BaseEventLoop loop: The event loop to use for async operations. :param int max_frame_size: The maximum websocket frame size to allow. :param int retries: When connecting or reconnecting, and all endpoints fail, how many times to retry the connection before giving up. :param int retry_backoff: Number of seconds to increase the wait between connection retry attempts (a backoff of 10 with 3 retries would wait 10s, 20s, and 30s). :param specified_facades: Define a series of facade versions you wish to override to prevent using the conservative client pinning with in the client. """ self = cls() if endpoint is None: raise ValueError('no endpoint provided') if not isinstance(endpoint, str) and not isinstance(endpoint, list): raise TypeError("Endpoint should be either str or list") self.uuid = uuid if bakery_client is None: bakery_client = httpbakery.Client() self.bakery_client = bakery_client if username and '@' in username and not username.endswith('@local'): # We're trying to log in as an external user - we need to use # macaroon authentication with no username or password. if password is not None: raise errors.JujuAuthError('cannot log in as external ' 'user with a password') username = None self.usertag = tag.user(username) self.password = password self.loop = loop or asyncio.get_event_loop() self.__request_id__ = 0 # The following instance variables are initialized by the # _connect_with_redirect method, but create them here # as a reminder that they will exist. self.addr = None self.ws = None self.endpoint = None self.endpoints = None self.cacert = None self.info = None # Create that _Task objects but don't start the tasks yet. self._pinger_task = _Task(self._pinger, self.loop) self._receiver_task = _Task(self._receiver, self.loop) self._retries = retries self._retry_backoff = retry_backoff self.facades = {} self.specified_facades = specified_facades or {} self.messages = IdQueue(loop=self.loop) self.monitor = Monitor(connection=self) if max_frame_size is None: max_frame_size = self.MAX_FRAME_SIZE self.max_frame_size = max_frame_size _endpoints = [(endpoint, cacert)] if isinstance( endpoint, str) else [(e, cacert) for e in endpoint] for _ep in _endpoints: try: await self._connect_with_redirect([_ep]) return self except OSError as e: logging.debug("Cannot access endpoint {}: {}".format( _ep, e.strerror)) continue raise Exception("Unable to connect to websocket")