Ejemplo n.º 1
0
 def __init__(self, ip, port, api_token,
              need_human_ob=False,
              max_containable_step=10,
              logfile_path='./',
              debug=False):
     self.grpc_client = GrpcClient(ip, port, api_token, logfile_path, debug)
     self.need_human_ob = need_human_ob
     self.max_containable_step = max_containable_step
     self._frame_period = self.grpc_client.get_system_info().frame_period
     self._last_action_frame = 0
     self._refresh_obs = RefreshObservation(self.grpc_client, need_human_ob)
     self._action_space = None
     self._reincarnation_flag = True
Ejemplo n.º 2
0
    def get_vcore_subscription(self):
        log.debug('start-get-vcore-subscription')

        while self.running and self.subscription is None:
            try:
                # If a subscription is not yet assigned then establish new GRPC connection
                # ... otherwise keep using existing connection details
                if self.subscription is None:
                    self._assign_grpc_attributes()

                # Send subscription request to register the current ofagent instance
                container_name = self.instance_id
                if self.grpc_client is None:
                    self.grpc_client = GrpcClient(self, self.channel,
                                                  self.grpc_timeout,
                                                  self.core_binding_key,
                                                  self.core_transaction_key)
                subscription = yield self.grpc_client.subscribe(
                    OfAgentSubscriber(ofagent_id=container_name))

                # If the subscriber id matches the current instance
                # ... then the subscription has succeeded
                if subscription is not None and subscription.ofagent_id == container_name:
                    if self.subscription is None:
                        # Keep details on the current GRPC session and subscription
                        log.debug('subscription-with-vcore-successful',
                                  subscription=subscription)
                        self.subscription = subscription
                        self.grpc_client.start()

                    # Sleep a bit in between each subscribe
                    yield asleep(self.subscription_refresh_interval)

                    # Move on to next subscribe request
                    continue

                # The subscription did not succeed, reset and move on
                else:
                    log.info('subscription-with-vcore-unavailable',
                             subscription=subscription)

            except _Rendezvous, e:
                log.error('subscription-with-vcore-terminated',
                          exception=e,
                          status=e.code())

            except Exception as e:
                log.exception('unexpected-subscription-termination-with-vcore',
                              e=e)
Ejemplo n.º 3
0
 def __init__(self,
              ip,
              port,
              api_token,
              need_human_ob=False,
              max_containable_step=10,
              logfile_path='./',
              debug=False):
     self.grpc_client = GrpcClient(ip, port, api_token, logfile_path, debug)
     self._check_frame = CheckFrame(self.grpc_client, need_human_ob)
     self.need_human_ob = need_human_ob
     self.last_action_frame = 0
     self.max_containable_step = max_containable_step
     self._action_space = None
     self._reincarnation_flag = True
Ejemplo n.º 4
0
    def start(self):

        if self.running:
            return

        log.debug('starting')

        self.running = True

        # Get voltha grpc endpoint
        self.channel = self.get_grpc_channel_with_voltha()

        # Create shared gRPC API object
        self.grpc_client = GrpcClient(self, self.channel).start()

        # Start monitoring logical devices and manage agents accordingly
        reactor.callLater(0, self.monitor_logical_devices)

        log.info('started')

        return self
Ejemplo n.º 5
0
class ConnectionManager(object):
    def __init__(self,
                 consul_endpoint,
                 vcore_endpoint,
                 vcore_grpc_timeout,
                 vcore_binding_key,
                 vcore_transaction_key,
                 controller_endpoints,
                 instance_id,
                 enable_tls=False,
                 key_file=None,
                 cert_file=None,
                 vcore_retry_interval=0.5,
                 devices_refresh_interval=5,
                 subscription_refresh_interval=5):

        log.info('init-connection-manager')
        log.info('list-of-controllers',
                 controller_endpoints=controller_endpoints)
        self.controller_endpoints = controller_endpoints
        self.consul_endpoint = consul_endpoint
        self.vcore_endpoint = vcore_endpoint
        self.grpc_timeout = vcore_grpc_timeout
        self.core_binding_key = vcore_binding_key
        self.core_transaction_key = vcore_transaction_key
        self.instance_id = instance_id
        self.enable_tls = enable_tls
        self.key_file = key_file
        self.cert_file = cert_file

        self.channel = None
        self.grpc_client = None  # single, shared gRPC client to vcore

        self.agent_map = {}  # (datapath_id, controller_endpoint) -> Agent()
        self.device_id_to_datapath_id_map = {}

        self.vcore_retry_interval = vcore_retry_interval
        self.devices_refresh_interval = devices_refresh_interval
        self.subscription_refresh_interval = subscription_refresh_interval
        self.subscription = None

        self.running = False

    def start(self):

        if self.running:
            return

        log.debug('starting')

        self.running = True

        # Get a subscription to vcore
        reactor.callInThread(self.get_vcore_subscription)

        # Start monitoring logical devices and manage agents accordingly
        reactor.callLater(0, self.monitor_logical_devices)

        log.info('started')

        return self

    def stop(self):
        log.debug('stopping')
        # clean up all controller connections
        for agent in self.agent_map.itervalues():
            agent.stop()
        self.running = False

        self._reset_grpc_attributes()

        log.info('stopped')

    def resolve_endpoint(self, endpoint):
        ip_port_endpoint = endpoint
        if endpoint.startswith('@'):
            try:
                ip_port_endpoint = get_endpoint_from_consul(
                    self.consul_endpoint, endpoint[1:])
                log.info('{}-service-endpoint-found'.format(endpoint),
                         address=ip_port_endpoint)
            except Exception as e:
                log.error('{}-service-endpoint-not-found'.format(endpoint),
                          exception=repr(e))
                log.error('committing-suicide')
                # Committing suicide in order to let docker restart ofagent
                os.system("kill -15 {}".format(os.getpid()))
        if ip_port_endpoint:
            host, port = ip_port_endpoint.split(':', 2)
            return host, int(port)

    def _reset_grpc_attributes(self):
        log.debug('start-reset-grpc-attributes')

        if self.grpc_client is not None:
            self.grpc_client.stop()

        if self.channel is not None:
            del self.channel

        self.is_alive = False
        self.channel = None
        self.subscription = None
        self.grpc_client = None

        log.debug('stop-reset-grpc-attributes')

    def _assign_grpc_attributes(self):
        log.debug('start-assign-grpc-attributes')

        host, port = self.resolve_endpoint(self.vcore_endpoint)
        log.info('revolved-vcore-endpoint',
                 endpoint=self.vcore_endpoint,
                 host=host,
                 port=port)

        assert host is not None
        assert port is not None

        # Establish a connection to the vcore GRPC server
        self.channel = grpc.insecure_channel('{}:{}'.format(host, port))
        self.is_alive = True

        log.debug('stop-assign-grpc-attributes')

    @inlineCallbacks
    def get_vcore_subscription(self):
        log.debug('start-get-vcore-subscription')

        while self.running and self.subscription is None:
            try:
                # If a subscription is not yet assigned then establish new GRPC connection
                # ... otherwise keep using existing connection details
                if self.subscription is None:
                    self._assign_grpc_attributes()

                # Send subscription request to register the current ofagent instance
                container_name = self.instance_id
                if self.grpc_client is None:
                    self.grpc_client = GrpcClient(self, self.channel,
                                                  self.grpc_timeout,
                                                  self.core_binding_key,
                                                  self.core_transaction_key)
                subscription = yield self.grpc_client.subscribe(
                    OfAgentSubscriber(ofagent_id=container_name))

                # If the subscriber id matches the current instance
                # ... then the subscription has succeeded
                if subscription is not None and subscription.ofagent_id == container_name:
                    if self.subscription is None:
                        # Keep details on the current GRPC session and subscription
                        log.debug('subscription-with-vcore-successful',
                                  subscription=subscription)
                        self.subscription = subscription
                        self.grpc_client.start()

                    # Sleep a bit in between each subscribe
                    yield asleep(self.subscription_refresh_interval)

                    # Move on to next subscribe request
                    continue

                # The subscription did not succeed, reset and move on
                else:
                    log.info('subscription-with-vcore-unavailable',
                             subscription=subscription)

            except _Rendezvous, e:
                log.error('subscription-with-vcore-terminated',
                          exception=e,
                          status=e.code())

            except Exception as e:
                log.exception('unexpected-subscription-termination-with-vcore',
                              e=e)

            # Reset grpc details
            # The vcore instance is either not available for subscription
            # or a failure occurred with the existing communication.
            self._reset_grpc_attributes()

            # Sleep for a short period and retry
            yield asleep(self.vcore_retry_interval)
Ejemplo n.º 6
0
class GameEnvironment:
    def __init__(self, ip, port, api_token,
                 need_human_ob=False,
                 max_containable_step=10,
                 logfile_path='./',
                 debug=False):
        self.grpc_client = GrpcClient(ip, port, api_token, logfile_path, debug)
        self.need_human_ob = need_human_ob
        self.max_containable_step = max_containable_step
        self._frame_period = self.grpc_client.get_system_info().frame_period
        self._last_action_frame = 0
        self._refresh_obs = RefreshObservation(self.grpc_client, need_human_ob)
        self._action_space = None
        self._reincarnation_flag = True

    def create_room(self, password):
        rsp = self.grpc_client.create_room(password)
        if rsp.err_code == 0:
            self._refresh_obs.start()
            return rsp.room_id, rsp.state
        else:
            return None

    def join_room(self, room_id, password):
        rsp = self.grpc_client.join_room(room_id, password)
        if rsp.err_code == 0:
            self._refresh_obs.start()
            return rsp.state
        else:
            return None

    def get_action_space(self):
        if self._action_space is None:
            self._action_space = self.grpc_client.get_action_space()
        return self._action_space.move, self._action_space.swing, self._action_space.fire, self._action_space.apply

    def get_inform(self):
        inform = self.grpc_client.get_inform()
        return inform.score, inform.kills, inform.health, inform.state, inform.frame_index

    def get_frame_period(self):
        return self._frame_period

    def submit_reincarnation(self):
        rsp = self.grpc_client.submit_reincarnation()
        if rsp.err_code == 0:
            return rsp.state
        else:
            return None

    def submit_action(self, frame, move, swing, fire, apply):
        """read"""
        frame_lock.acquire_read()
        current_frame = frame_index
        frame_lock.release()
        if self._last_action_frame < frame and frame > current_frame - self.max_containable_step:
            rsp = self.grpc_client.submit_action(move, swing, fire, apply)
            if rsp.err_code == 0:
                self._last_action_frame = frame
                return rsp.state
            else:
                return None
        else:
            return None

    def get_observation_with_info(self):
        """read"""
        observation_lock.acquire_read()
        state = observation_state
        location = location_observation
        immutable_element = immutable_element_observation
        mutable_element = mutable_element_observation
        bodies = bodies_observation
        asset_ownership = asset_ownership_observation
        self_asset = self_asset_observation
        self_status = self_status_observation
        pointer = pointer_observation
        human = human_observation
        observation_lock.release()

        frame_lock.acquire_read()
        frame = frame_index
        frame_lock.release()

        inform_lock.acquire_read()
        score = score_inform
        kill = kill_inform
        heath = heath_inform
        inform_lock.release()

        if self.need_human_ob:
            return frame, \
                   state, \
                   location, \
                   immutable_element, \
                   mutable_element, \
                   bodies, \
                   asset_ownership, \
                   self_asset, \
                   self_status, \
                   pointer, \
                   human, \
                   score, \
                   kill, \
                   heath

        else:
            return frame, \
                   state, \
                   location, \
                   immutable_element, \
                   mutable_element, \
                   bodies, \
                   asset_ownership, \
                   self_asset, \
                   self_status, \
                   pointer, \
                   score, \
                   kill, \
                   heath

    def get_move_meanings(self):
        return [MOVE_MEANING[i] for i in self._action_space.move]

    def show_image(self, image, height=100, width=200):
        plt.close('all')
        image_array = np.array(image).reshape(height, width)
        plt.imshow(image_array, cmap='gray')
        plt.show()

    @staticmethod
    def get_state_meanings():
        return STATE_MEANING
Ejemplo n.º 7
0
class ConnectionManager(object):
    def __init__(self,
                 consul_endpoint,
                 voltha_endpoint,
                 controller_endpoints,
                 voltha_retry_interval=0.5,
                 devices_refresh_interval=5):

        log.info('init-connection-manager')
        log.info('list-of-controllers',
                 controller_endpoints=controller_endpoints)
        self.controller_endpoints = controller_endpoints
        self.consul_endpoint = consul_endpoint
        self.voltha_endpoint = voltha_endpoint

        self.channel = None
        self.grpc_client = None  # single, shared gRPC client to Voltha

        self.agent_map = {}  # (datapath_id, controller_endpoint) -> Agent()
        self.device_id_to_datapath_id_map = {}

        self.voltha_retry_interval = voltha_retry_interval
        self.devices_refresh_interval = devices_refresh_interval

        self.running = False

    def start(self):

        if self.running:
            return

        log.debug('starting')

        self.running = True

        # Get voltha grpc endpoint
        self.channel = self.get_grpc_channel_with_voltha()

        # Create shared gRPC API object
        self.grpc_client = GrpcClient(self, self.channel).start()

        # Start monitoring logical devices and manage agents accordingly
        reactor.callLater(0, self.monitor_logical_devices)

        log.info('started')

        return self

    def stop(self):
        log.debug('stopping')
        # clean up all controller connections
        for agent in self.agent_map.itervalues():
            agent.stop()
        self.running = False
        self.grpc_client.stop()
        del self.channel
        log.info('stopped')

    def resolve_endpoint(self, endpoint):
        ip_port_endpoint = endpoint
        if endpoint.startswith('@'):
            try:
                ip_port_endpoint = get_endpoint_from_consul(
                    self.consul_endpoint, endpoint[1:])
                log.info('Found endpoint {} service at {}'.format(
                    endpoint, ip_port_endpoint))
            except Exception as e:
                log.error('Failure to locate {} service from '
                          'consul {}:'.format(endpoint, repr(e)))
                log.error('Committing suicide...')
                # Committing suicide in order to let docker restart ofagent
                os.system("kill -15 {}".format(os.getpid()))
        if ip_port_endpoint:
            host, port = ip_port_endpoint.split(':', 2)
            return host, int(port)

    def get_grpc_channel_with_voltha(self):
        log.info('Resolving voltha endpoint {} from consul'.format(
            self.voltha_endpoint))
        host, port = self.resolve_endpoint(self.voltha_endpoint)
        assert host is not None
        assert port is not None
        # Create grpc channel to Voltha
        channel = grpc.insecure_channel('{}:{}'.format(host, port))
        log.info('Acquired a grpc channel to voltha')
        return channel

    @inlineCallbacks
    def get_list_of_logical_devices_from_voltha(self):

        while True:
            log.info('Retrieve devices from voltha')
            try:
                stub = voltha_pb2.VolthaLocalServiceStub(self.channel)
                devices = stub.ListLogicalDevices(Empty()).items
                for device in devices:
                    log.info("Devices {} -> {}".format(device.id,
                                                       device.datapath_id))
                returnValue(devices)

            except _Rendezvous, e:
                if e.code() == StatusCode.UNAVAILABLE:
                    os.system("kill -15 {}".format(os.getpid()))

            except Exception as e:
                log.error('Failure to retrieve devices from '
                          'voltha: {}'.format(repr(e)))

            log.info('reconnect', after_delay=self.voltha_retry_interval)
            yield asleep(self.voltha_retry_interval)
Ejemplo n.º 8
0
class ConnectionManager(object):
    def __init__(self,
                 consul_endpoint,
                 voltha_endpoint,
                 controller_endpoint,
                 voltha_retry_interval=0.5,
                 devices_refresh_interval=5):

        log.info('init-connection-manager')
        self.controller_endpoint = controller_endpoint
        self.consul_endpoint = consul_endpoint
        self.voltha_endpoint = voltha_endpoint

        self.channel = None
        self.grpc_client = None  # single, shared gRPC client to Voltha

        self.agent_map = {}  # datapath_id -> Agent()
        self.device_id_to_datapath_id_map = {}

        self.voltha_retry_interval = voltha_retry_interval
        self.devices_refresh_interval = devices_refresh_interval

        self.running = False

    def start(self):

        if self.running:
            return

        log.debug('starting')

        self.running = True

        # Get voltha grpc endpoint
        self.channel = self.get_grpc_channel_with_voltha()

        # Create shared gRPC API object
        self.grpc_client = GrpcClient(self, self.channel).start()

        # Start monitoring logical devices and manage agents accordingly
        reactor.callLater(0, self.monitor_logical_devices)

        log.info('started')

        return self

    def stop(self):
        log.debug('stopping')
        # clean up all controller connections
        for agent in self.agent_map.itervalues():
            agent.stop()
        self.running = False
        self.grpc_client.stop()
        del self.channel
        log.info('stopped')

    def resolve_endpoint(self, endpoint):
        ip_port_endpoint = endpoint
        if endpoint.startswith('@'):
            try:
                ip_port_endpoint = get_endpoint_from_consul(
                    self.consul_endpoint, endpoint[1:])
                log.info('Found endpoint {} service at {}'.format(
                    endpoint, ip_port_endpoint))
            except Exception as e:
                log.error('Failure to locate {} service from '
                          'consul {}:'.format(endpoint, repr(e)))
                log.error('Committing suicide...')
                # Committing suicide in order to let docker restart ofagent
                os.system("kill -15 {}".format(os.getpid()))
        if ip_port_endpoint:
            host, port = ip_port_endpoint.split(':', 2)
            return host, int(port)

    def get_grpc_channel_with_voltha(self):
        log.info('Resolving voltha endpoint {} from consul'.format(
            self.voltha_endpoint))
        host, port = self.resolve_endpoint(self.voltha_endpoint)
        assert host is not None
        assert port is not None
        # Create grpc channel to Voltha
        channel = grpc.insecure_channel('{}:{}'.format(host, port))
        log.info('Acquired a grpc channel to voltha')
        return channel

    @inlineCallbacks
    def get_list_of_logical_devices_from_voltha(self):

        while True:
            log.info('Retrieve devices from voltha')
            try:
                stub = voltha_pb2.VolthaLocalServiceStub(self.channel)
                devices = stub.ListLogicalDevices(Empty()).items
                for device in devices:
                    log.info("Devices {} -> {}".format(device.id,
                                                       device.datapath_id))
                returnValue(devices)

            except Exception as e:
                log.error('Failure to retrieve devices from '
                          'voltha: {}'.format(repr(e)))

            log.info('reconnect', after_delay=self.voltha_retry_interval)
            yield asleep(self.voltha_retry_interval)

    def refresh_agent_connections(self, devices):
        """
        Based on the new device list, update the following state in the class:
        * agent_map
        * datapath_map
        * device_id_map
        :param devices: full device list freshly received from Voltha
        :return: None
        """

        # Use datapath ids for deciding what's new and what's obsolete
        desired_datapath_ids = set(d.datapath_id for d in devices)
        current_datapath_ids = set(self.agent_map.iterkeys())

        # if identical, nothing to do
        if desired_datapath_ids == current_datapath_ids:
            return

        # ... otherwise calculate differences
        to_add = desired_datapath_ids.difference(current_datapath_ids)
        to_del = current_datapath_ids.difference(desired_datapath_ids)

        # remove what we don't need
        for datapath_id in to_del:
            self.delete_agent(datapath_id)

        # start new agents as needed
        for device in devices:
            if device.datapath_id in to_add:
                self.create_agent(device)

        log.debug('updated-agent-list', count=len(self.agent_map))
        log.debug('updated-device-id-to-datapath-id-map',
                  map=str(self.device_id_to_datapath_id_map))

    def create_agent(self, device):
        datapath_id = device.datapath_id
        device_id = device.id
        agent = Agent(self.controller_endpoint, datapath_id, device_id,
                      self.grpc_client)
        agent.start()
        self.agent_map[datapath_id] = agent
        self.device_id_to_datapath_id_map[device_id] = datapath_id

    def delete_agent(self, datapath_id):
        agent = self.agent_map[datapath_id]
        device_id = agent.get_device_id()
        agent.stop()
        del self.agent_map[datapath_id]
        del self.device_id_to_datapath_id_map[device_id]

    @inlineCallbacks
    def monitor_logical_devices(self):
        while True:
            # should change to a gRPC streaming call
            # see https://jira.opencord.org/browse/CORD-821

            # get current list from Voltha
            devices = yield self.get_list_of_logical_devices_from_voltha()

            # update agent list and mapping tables as needed
            self.refresh_agent_connections(devices)

            # wait before next poll
            yield asleep(self.devices_refresh_interval)
            log.info('Monitor connections')

    def forward_packet_in(self, device_id, ofp_packet_in):
        datapath_id = self.device_id_to_datapath_id_map.get(device_id, None)
        if datapath_id:
            agent = self.agent_map[datapath_id]
            agent.forward_packet_in(ofp_packet_in)

    def forward_change_event(self, device_id, event):
        datapath_id = self.device_id_to_datapath_id_map.get(device_id, None)
        if datapath_id:
            agent = self.agent_map[datapath_id]
            agent.forward_change_event(event)
Ejemplo n.º 9
0
class GameEnvironment:
    def __init__(self,
                 ip,
                 port,
                 api_token,
                 need_human_ob=False,
                 max_containable_step=10,
                 logfile_path='./',
                 debug=False):
        self.grpc_client = GrpcClient(ip, port, api_token, logfile_path, debug)
        self._check_frame = CheckFrame(self.grpc_client, need_human_ob)
        self.need_human_ob = need_human_ob
        self.last_action_frame = 0
        self.max_containable_step = max_containable_step
        self._action_space = None
        self._reincarnation_flag = True

    def create_room(self, password):
        rsp = self.grpc_client.create_room(password)
        if rsp.err_code == 0:
            self._check_frame.start()
            return rsp.room_id, rsp.state
        else:
            return None

    def join_room(self, room_id, password):
        rsp = self.grpc_client.join_room(room_id, password)
        if rsp.err_code == 0:
            self._check_frame.start()
            return rsp.state
        else:
            return None

    def get_action_space(self):
        if self._action_space is None:
            self._action_space = self.grpc_client.get_action_space()
        return self._action_space.move, self._action_space.swing, self._action_space.fire, self._action_space.apply

    def get_inform(self):
        inform = self.grpc_client.get_inform()
        return inform.score, inform.kills, inform.health, inform.state, inform.frame_index

    def submit_reincarnation(self):
        if self._reincarnation_flag:
            rsp = self.grpc_client.submit_reincarnation()
            if rsp.err_code == 0:
                self._reincarnation_flag = False
                return rsp.state
            else:
                return None
        else:
            return None

    def submit_action(self, frame, move, swing, fire, apply):
        """read"""
        frame_lock.acquire_read()
        current_frame = frame
        frame_lock.release()
        if self.last_action_frame < frame and frame > current_frame - self.max_containable_step:
            rsp = self.grpc_client.submit_action(move, swing, fire, apply)
            if rsp.err_code == 0:
                self.last_action_frame = frame
                return rsp.state
            else:
                return None
        else:
            return None

    def get_observation_with_info(self):
        """read"""
        observation_lock.acquire_read()
        state = observation_state
        location = location_observation
        immutable_element = immutable_element_observation
        mutable_element = mutable_element_observation
        bodies = bodies_observation
        asset_ownership = asset_ownership_observation
        self_asset = self_asset_observation
        asset_status = asset_status_observation
        pointer = pointer_observation
        human = human_observation
        observation_lock.release()

        frame_lock.acquire_read()
        frame = frame_index
        frame_lock.release()

        inform_lock.acquire_read()
        score = score_inform
        kill = kill_inform
        heath = heath_inform
        inform_lock.release()

        if state == api.in_game and self._reincarnation_flag is False:
            self._reincarnation_flag = True

        if self.need_human_ob:
            return frame, \
                   state, \
                   location, \
                   immutable_element, \
                   mutable_element, \
                   bodies, \
                   asset_ownership, \
                   self_asset, \
                   asset_status, \
                   pointer, \
                   human, \
                   score, \
                   kill, \
                   heath

        else:
            return frame, \
                   state, \
                   location, \
                   immutable_element, \
                   mutable_element, \
                   bodies, \
                   asset_ownership, \
                   self_asset, \
                   asset_status, \
                   pointer, \
                   score, \
                   kill, \
                   heath

    def get_move_meanings(self):
        return [MOVE_MEANING[i] for i in self._action_space.move]

    @staticmethod
    def get_state_meanings():
        return STATE_MEANING