class DeploymentPlanner(object):
    """
    A deployment activator validates that a set of devices will map to a set of sites in one unique way

    its primary purpose is to prepare( ) after which you'll be able to access what associations must be made (and unmade)

    """

    def __init__(self, clients=None, enhanced_rr=None):
        self.clients = clients
        self.enhanced_rr = enhanced_rr

        if not enhanced_rr:
            self.enhanced_rr = EnhancedResourceRegistryClient(self.clients.resource_registry)
        self.outil = ObservatoryUtil(self, enhanced_rr=self.enhanced_rr)

        #self.resource_collector= DeploymentResourceCollector(self.clients, self.enhanced_rr)
        #self.resource_collector = resource_collector.create(self.deployment_obj)

    def _find_top_site_device(self, deployment_id):
        top_site = ''
        top_device = ''
        #retrieve the site tree information using the OUTIL functions; site info as well has site children
        deploy_items_objs, _ = self.clients.resource_registry.find_subjects(predicate=PRED.hasDeployment, object=deployment_id, id_only=False)
        log.debug("site_ids associated to this deployment: %s", deploy_items_objs)
        for obj in deploy_items_objs:
            rsrc_type = obj.type_
            log.debug("resource type associated to this deployment:: %s", rsrc_type)
            if RT.PlatformDevice == rsrc_type or RT.InstrumentDevice == rsrc_type:
                top_device = obj
            elif RT.PlatformSite == rsrc_type or RT.InstrumentSite == rsrc_type:
                top_site = obj
            else:
                log.error('Deployment may only link to devices and sites. Deployment: %s', str(self.deployment_obj))

        if not top_device or not top_site:
            log.error('Deployment must associate to both site and device. Deployment: %s', str(self.deployment_obj))
            raise BadRequest('Deployment must associate to both site and device. Deployment: %s', str(self.deployment_obj))

        return top_site, top_device


    def _find_pairs_to_remove(self):
        #figure out if any of the devices in the new mapping are already mapped and need to be removed
        pairs_to_remove = []
        pairs_to_ignore = []
        for (s, d) in self.match_list:
            rm_pair, ignore_pair = self._find_existing_relationship(s, d)
            if rm_pair:
                pairs_to_remove.append(rm_pair)
            if ignore_pair:
                pairs_to_ignore.append(ignore_pair)

        log.info("Pairs to ignore (will be removed from add list): %s", pairs_to_ignore)

        # make sure that anything being removed is not also being added
        self.match_list = filter(lambda x: x not in pairs_to_ignore, self.match_list)

        log.info("Pairs to remove: %s", pairs_to_remove)
        self.remove_list = pairs_to_remove


    def _find_existing_relationship(self, site_id, device_id, site_type=None, device_type=None):
        # look for an existing relationship between the site_id and another device.
        # if this site/device pair already exists, we leave it alone
        assert(type("") == type(site_id) == type(device_id))

        log.debug("checking %s/%s pair for deployment", site_type, device_type)
        #return a pair that should be REMOVED, or None

        if site_type is None and site_id in self.site_resources:
            site_type = self.site_resources[site_id].type_

        if device_type is None and device_id in self.device_resources:
            device_type = self.device_resources[device_id].type_

        log.debug("checking existing %s hasDevice %s links", site_type, device_type)

        ret_remove = None
        ret_ignore = None

        try:
            found_device_id = self.enhanced_rr.find_object(site_id, PRED.hasDevice, device_type, True)

            if found_device_id == device_id:
                ret_ignore = (site_id, device_id)
            else:
                ret_remove = (site_id, found_device_id)
                log.warning("%s '%s' already hasDevice %s", site_type, site_id, device_type)

        except NotFound:
            pass

        return ret_remove, ret_ignore


    def _get_site_ref_designator_map(self):
        # create a map of site ids to their reference designator codes to facilitate matching
        site_ref_designator_map = {}
        for id, site_obj in self.site_resources.iteritems():
            site_ref_designator_map[site_obj.reference_designator] = id
        log.debug("prepare_activation site_ref_designator_map: %s", site_ref_designator_map)
        return site_ref_designator_map


    def _get_device_resources(self, device_tree):
        # create a map of device ids to their full resource object to assit with lookup and validation
        device_objs = self.clients.resource_registry.read_mult(device_tree.keys())
        log.debug("prepare_activation device_objectss: %s", device_objs)
        for device_obj in device_objs:
            self.device_resources[device_obj._id] = device_obj


    def _get_models(self):
        # retrieve all hasModel associations from the registry then filter
        models_tuples = {}
        assoc_list = self.outil._get_predicate_assocs(PRED.hasModel)
        for assoc in assoc_list:
            # only include these subject types in the map
            if assoc.st in [RT.InstrumentDevice, RT.InstrumentSite, RT.PlatformDevice, RT.PlatformSite]:
                if assoc.s not in models_tuples:
                    models_tuples[assoc.s] = []
                # a site may support more than one model so map to a list of models
                models_tuples[assoc.s].append((assoc.st, assoc.o, assoc.ot))
                if assoc.s not in self.models_map:
                    self.models_map[assoc.s] = []
                self.models_map[assoc.s].append(assoc.o)
        log.debug("models_map: %s", self.models_map )


    def _validate_models(self, site_id, device_id):
        # validate that the device and the site models are compatible
        if device_id in self.models_map:
            device_model_list = self.models_map[device_id]
            # devices should only be associated to one model
            if len(device_model_list) != 1:
                log.error("Device not associated to one distinct model. Device id: %s", device_id)

            elif  device_model_list and device_model_list[0] not in  self.models_map[site_id]:
                log.error("Device and Site to not share a compatible model. Device id: %s   Site id: %s", site_id)
        else:
            log.error("Device not associated with a device model. Device id: %s", device_id)
            raise NotFound("Device not associated with a device model. Device id: %s", device_id)


    def _validate_port_assignments(self, device_id, platform_port):
        deployment_context_type = type(self.deployment_obj.context).__name__

        self._validate_ooi_reference_designator(device_id, platform_port)

        # a one-to-one deployment of a device onto an RSN platform
        if OT.CabledInstrumentDeploymentContext == deployment_context_type or \
            OT.CabledNodeDeploymentContext == deployment_context_type:

            # validate IP address for a cabled node deployment
            from socket import inet_aton
            try:
                inet_aton(platform_port.ip_address)
            except :
                log.error('IP address validation failed for device. Device id: %s', device_id)

        # validate port_type based on deployment context
        # a platform device deployment should have UPLINK port type
        if OT.RemotePlatformDeploymentContext == deployment_context_type or \
            OT.CabledNodeDeploymentContext == deployment_context_type:
            if device_id in self.device_resources and self.device_resources[device_id].type_ is RT.PlatformDevice:
                if platform_port.port_type != PortTypeEnum.UPLINK:
                    log.warning('Type of port for platform port assignment should be UPLINK.  Device id: %s', device_id)

        #validate that parent_id is provided
        if not platform_port.parent_id:
            log.warning('Id of parent device should be provided in port assignment information. Device id: %s', device_id)


    def _validate_ooi_reference_designator(self, device_id, device_port):
        ooi_rd = OOIReferenceDesignator(device_port.reference_designator)
        if ooi_rd.error:
           log.warning("Invalid OOIReferenceDesignator ( %s ) specified for device %s", device_port.reference_designator, device_id)
        if not ooi_rd.port:
            log.warning("Invalid OOIReferenceDesignator ( %s ) specified for device %s, could not retrieve port", device_port.reference_designator, device_id)


    def get_deployment_sites_devices(self, deployment_obj):
        # retrieve all site and device ids related to this deployment
        site_ids = []
        device_ids = []
        self.outil = ObservatoryUtil(self, enhanced_rr=self.enhanced_rr)

        top_site, top_device = self._find_top_site_device(deployment_obj._id)

        site_resources, site_children = self.outil.get_child_sites( parent_site_id=top_site._id, id_only=False)
        site_ids = site_resources.keys()

        # get_site_devices returns a tuple that includes all devices linked to deployment sites
        site_devices = self.outil.get_site_devices(site_ids)
        for site, tuple_list in site_devices.iteritems():
            for (site_type, device_id, device_type) in tuple_list:
                device_ids.append(device_id)

        return site_ids, device_ids


    def prepare_activation(self, deployment_obj):
        """
        Prepare (validate) a deployment for activation, returning lists of what associations need to be added
        and which ones need to be removed.
        """

        self.match_list = []
        self.remove_list = []
        self.unmatched_device_list = []

        self.models_map = {}

        self.top_device = ''
        self.top_site = ''
        self.deployment_obj = deployment_obj
        self.site_resources = {}
        self.device_resources = {}

        self.outil = ObservatoryUtil(self, enhanced_rr=self.enhanced_rr)

        # retrieve the site tree information using the OUTIL functions; site info as well has site children
        self.top_site, self.top_device = self._find_top_site_device(deployment_obj._id)
        # must have a site and a device to continue
        if not self.top_site or not self.top_device:
            return [], []

        log.debug("port_assignments: %s", self.deployment_obj.port_assignments )

        # retrieve all models to use in match validation
        self._get_models()

        self.site_resources, site_children = self.outil.get_child_sites( parent_site_id=self.top_site._id, id_only=False)

        log.debug("site_resources: %s", self.site_resources)
        log.debug("site_children: %s", site_children)

        site_ref_designator_map = self._get_site_ref_designator_map()

        # retrieve the device tree from outil then cache the device resources
        device_tree = self.outil.get_child_devices(device_id=self.top_device._id)
        self._get_device_resources(device_tree)

        self._match_devices(self.top_device._id, device_tree, site_ref_designator_map)

        # check for hasDevice relations to remove and existing hasDevice relations
        self. _find_pairs_to_remove()

        if self.unmatched_device_list:
            log.warning("Devices not matched to sites: %s  ", self.unmatched_device_list)

        return self.remove_list, self.match_list


    def _match_devices(self, device_id, device_tree, site_ref_designator_map):

        # there will not be a port assignment for the top device
        if device_id == self.top_device._id:
            self._validate_models(self.top_site._id, self.top_device._id)
            self.match_list.append((self.top_site._id, self.top_device._id))

        tuple_list = device_tree[device_id]

        for (pt, child_id, ct) in tuple_list:
            log.debug("  tuple  - pt: %s  child_id: %s  ct: %s", pt, child_id, ct)

            # match this child device then if it has children, call _match_devices with this id

            # check that this device is represented in device tree and in port assignments
            if child_id in self.device_resources and child_id in self.deployment_obj.port_assignments:
                platform_port = self.deployment_obj.port_assignments[child_id]
                log.debug("device platform_port: %s", platform_port)

                # validate PlatformPort info for this device
                self._validate_port_assignments(child_id, platform_port)

                if platform_port.reference_designator in site_ref_designator_map:
                    matched_site = site_ref_designator_map[platform_port.reference_designator]
                    self._validate_models(matched_site, child_id)
                    log.info("match_list append site: %s  device: %s", matched_site, child_id)
                    self.match_list.append((matched_site, child_id))

                    #recurse on the children of this device
                    self._match_devices(child_id, device_tree, site_ref_designator_map)

            # otherwise cant be matched to a site
            else:
                self.unmatched_device_list.append(child_id)
class TestObservatoryUtil(IonUnitTestCase):

    def setUp(self):
        self.mu = MockUtil()
        self.process_mock = self.mu.create_process_mock()
        self.container_mock = self.mu.create_container_mock()
        self.dsm_mock = self.mu.create_device_status_manager_mock()

    res_list = [
        dict(rt='Org', _id='Org_1', attr={}),
        dict(rt='Observatory', _id='Obs_1', attr={}),
        dict(rt='Observatory', _id='Obs_2', attr={}),
        dict(rt='Subsite', _id='Sub_1', attr={}),
        dict(rt='Subsite', _id='Sub_2', attr={}),
        dict(rt='PlatformSite', _id='PS_1', attr={}),
        dict(rt='InstrumentSite', _id='IS_1', attr={}),

        dict(rt='PlatformDevice', _id='PD_1', attr={}),
        dict(rt='InstrumentDevice', _id='ID_1', attr={}),
    ]

    assoc_list = [
        ['Obs_1', 'hasSite', 'Sub_1'],
        ['Sub_1', 'hasSite', 'PS_1'],
        ['PS_1', 'hasSite', 'IS_1'],
    ]
    assoc_list1 = [
        ['Org_1', 'hasResource', 'Obs_1'],
        ['Org_1', 'hasResource', 'Obs_2'],
        ['Obs_2', 'hasSite', 'Sub_2'],
    ]
    assoc_list2 = [
        ['PS_1', 'hasDevice', 'PD_1'],
        ['IS_1', 'hasDevice', 'ID_1'],

        ['PD_1', 'hasDevice', 'ID_1'],
    ]

    def spy_get_child_sites(self, parent_site_id=None, org_id=None, exclude_types=None, include_parents=True, id_only=True):
        child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id=parent_site_id,
                                                                    org_id=org_id,
                                                                    exclude_types=exclude_types,
                                                                    include_parents=include_parents,
                                                                    id_only=id_only)

        print "child_sites of", parent_site_id, "are", child_sites
        print "site_ancestors of", parent_site_id, "are", site_ancestors

        return child_sites, site_ancestors

    def test_get_child_sites(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='Obs_1', include_parents=False, id_only=True)
        self.assertEquals(len(site_resources), 3)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Sub_1', site_resources)
        self.assertIn('PS_1', site_resources)
        self.assertIn('IS_1', site_resources)
        self.assertNotIn('Obs_1', site_resources)
        self.assertEquals(len([v for v in site_resources.values() if v is None]), 3)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='Obs_1', include_parents=False, id_only=False)
        self.assertEquals(len(site_resources), 3)
        self.assertEquals(len(site_children), 3)
        self.assertEquals(len([v for v in site_resources.values() if v is None]), 0)
        self.assertEquals(site_resources['Sub_1']._get_type(), RT.Subsite)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='Obs_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Obs_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='Sub_1', include_parents=False)
        self.assertEquals(len(site_resources), 2)
        self.assertEquals(len(site_children), 2)
        self.assertNotIn('Sub_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='Sub_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Sub_1', site_resources)
        self.assertIn('Obs_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='PS_1', include_parents=False)
        self.assertEquals(len(site_resources), 1)
        self.assertEquals(len(site_children), 1)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='PS_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='IS_1', include_parents=False)
        self.assertEquals(len(site_resources), 0)
        self.assertEquals(len(site_children), 0)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='IS_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)

        site_resources, site_children = self.spy_get_child_sites(parent_site_id='XXX', include_parents=True)
        self.assertEquals(len(site_resources), 1)
        self.assertEquals(len(site_children), 0)

    def test_get_child_sites_org(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=False, id_only=True)
        self.assertEquals(len(child_sites), 6)
        self.assertEquals(len(site_ancestors), 5)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('PS_1', child_sites)
        self.assertIn('IS_1', child_sites)
        self.assertIn('Obs_1', child_sites)
        self.assertIn('Obs_2', child_sites)

        child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=True, id_only=True)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)

        child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=True, id_only=False)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)
        self.assertEquals(len([v for v in child_sites.values() if v is None]), 0)
        self.assertEquals(child_sites['Org_1']._get_type(), RT.Org)

    def test_get_site_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        site_devices = self.obs_util.get_site_devices(['Sub_1', 'PS_1', 'IS_1'])
        self.assertEquals(len(site_devices), 3)
        self.assertEquals(site_devices['Sub_1'], [])
        self.assertEquals(site_devices['IS_1'], [('InstrumentSite', 'ID_1', 'InstrumentDevice')])

    def test_get_child_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        child_devices = self.obs_util.get_child_devices('PD_1')
        self.assertEquals(len(child_devices), 2)
        self.assertEquals(child_devices['PD_1'][0][1], 'ID_1')

        child_devices = self.obs_util.get_child_devices('ID_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['ID_1'], [])

        child_devices = self.obs_util.get_child_devices('Sub_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['Sub_1'], [])

        child_devices = self.obs_util.get_child_devices('XXX')
        self.assertEquals(len(child_devices), 1)

    def test_get_device_data_products(self):
        self.mu.load_mock_resources(self.res_list + self.res_list1)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 + self.assoc_list2 + self.assoc_list3)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        res_dict = self.obs_util.get_site_data_products('Obs_1', RT.Observatory)
        self.assertGreaterEqual(len(res_dict), 6)
        self.assertIsNone(res_dict['data_product_resources'])
        self.assertIn('ID_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['ID_1']), 3)
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])
        self.assertIn('PD_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['PD_1']), 3)

        res_dict = self.obs_util.get_site_data_products('PS_1', RT.PlatformSite)
        self.assertEquals(len(res_dict['device_data_products']['ID_1']), 3)
        self.assertIn('ID_1', res_dict['device_data_products'])
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])
        self.assertIn('PD_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['PD_1']), 3)

        res_dict = self.obs_util.get_site_data_products('Org_1', RT.Org)
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])

        res_dict = self.obs_util.get_site_data_products('PS_1', RT.PlatformSite, include_data_products=True)
        self.assertIsNotNone(res_dict['data_product_resources'])
        self.assertIn('DP_1', res_dict['data_product_resources'])

        #import pprint
        #pprint.pprint(res_dict)


    status_by_device_1 = {
        "ID_1": _devstat("ID_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK),
        "PD_1": _devstat("PD_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK),
    }
    status_by_device_2 = {
        "ID_1": _devstat("ID_1", DST.STATUS_WARNING, DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK),
        "PD_1": _devstat("PD_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK),
    }
    status_by_device_3 = {
        "ID_1": _devstat("ID_1", DST.STATUS_WARNING, DST.STATUS_WARNING, DST.STATUS_OK, DST.STATUS_OK),
        "PD_1": _devstat("PD_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK),
    }
    status_by_device_4 = {
        "ID_1": _devstat("ID_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK),
        "PD_1": _devstat("PD_1", DST.STATUS_WARNING, DST.STATUS_WARNING, DST.STATUS_OK, DST.STATUS_OK),
    }


    def test_get_status_roll_ups(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 + self.assoc_list2)
        self.mu.load_mock_device_statuses(self.status_by_device_1)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock, device_status_mgr=self.dsm_mock)

        # No problems
        status_rollups = self.obs_util.get_status_roll_ups('ID_1', RT.InstrumentDevice)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('PD_1', RT.PlatformDevice)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Sub_1')
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Obs_1')
        self._assert_status(status_rollups, 'Sub_1')
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        # ID_1 power warning
        self.mu.load_mock_device_statuses(self.status_by_device_2)
        status_rollups = self.obs_util.get_status_roll_ups('ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups, 'ID_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('PD_1', RT.PlatformDevice)
        self._assert_status(status_rollups, 'PD_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('IS_1', RT.InstrumentSite)
        self.assertIn('IS_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('PS_1', RT.PlatformSite)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING)

        # ID_1 power+comms warning
        self.mu.load_mock_device_statuses(self.status_by_device_3)
        status_rollups = self.obs_util.get_status_roll_ups('ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups, 'ID_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('PD_1', RT.PlatformDevice)
        self._assert_status(status_rollups, 'PD_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Sub_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Obs_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'Sub_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)

    def test_get_status_roll_ups_platform_warn(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 + self.assoc_list2)
        self.mu.load_mock_device_statuses(self.status_by_device_4)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock, device_status_mgr=self.dsm_mock)

        # PD_1 power+comms warning
        status_rollups = self.obs_util.get_status_roll_ups('ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('PD_1', RT.PlatformDevice)
        #log.warn("status %s" % status_rollups)
        self._assert_status(status_rollups, 'PD_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Sub_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Obs_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'Sub_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PS_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1', agg=DST.STATUS_WARNING, power=DST.STATUS_WARNING, comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

    def _assert_status(self, status_rollups, res_id=None, agg=DST.STATUS_OK, loc=DST.STATUS_OK,
                       data=DST.STATUS_OK, comms=DST.STATUS_OK, power=DST.STATUS_OK):
        res_status = status_rollups[res_id] if res_id else status_rollups
        log.debug("_assert_status(%s) = %s", res_id, res_status)
        self.assertEquals(len(res_status), 5)
        if agg is not None:
            self.assertEquals(res_status['agg'], agg)
        if loc is not None:
            self.assertEquals(res_status[AggregateStatusType.AGGREGATE_LOCATION], loc)
        if data is not None:
            self.assertEquals(res_status[AggregateStatusType.AGGREGATE_DATA], data)
        if comms is not None:
            self.assertEquals(res_status[AggregateStatusType.AGGREGATE_COMMS], comms)
        if power is not None:
            self.assertEquals(res_status[AggregateStatusType.AGGREGATE_POWER], power)

    res_list1 = [
        dict(rt='DataProduct', _id='DP_1', attr={}),
        dict(rt='DataProduct', _id='DP_2', attr={}),
        dict(rt='DataProduct', _id='DP_3', attr={}),
        dict(rt='DataProduct', _id='DP_4', attr={}),
        dict(rt='DataProduct', _id='DP_5', attr={}),
        ]

    assoc_list3 = [
        ['DP_1', 'hasSource', 'ID_1'],
        ['DP_1', 'hasSource', 'IS_1'],
        ['DP_2', 'hasSource', 'ID_1'],
        ['DP_3', 'hasSource', 'ID_1'],
        ['DP_3', 'hasSource', 'PD_1'],
        ['DP_4', 'hasSource', 'PD_1'],
        ['DP_5', 'hasSource', 'PD_1'],
        ]
class TestObservatoryUtil(IonUnitTestCase):

    def setUp(self):
        self.mu = MockUtil()
        self.process_mock = self.mu.create_process_mock()
        self.container_mock = self.mu.create_container_mock()

    res_list = [
        dict(rt='Org', _id='Org_1', attr={}),
        dict(rt='Observatory', _id='Obs_1', attr={}),
        dict(rt='Observatory', _id='Obs_2', attr={}),
        dict(rt='Subsite', _id='Sub_1', attr={}),
        dict(rt='Subsite', _id='Sub_2', attr={}),
        dict(rt='PlatformSite', _id='PS_1', attr={}),
        dict(rt='InstrumentSite', _id='IS_1', attr={}),

        dict(rt='PlatformDevice', _id='PD_1', attr={}),
        dict(rt='InstrumentDevice', _id='ID_1', attr={}),
    ]

    assoc_list = [
        ['Obs_1', 'hasSite', 'Sub_1'],
        ['Sub_1', 'hasSite', 'PS_1'],
        ['PS_1', 'hasSite', 'IS_1'],
    ]
    assoc_list1 = [
        ['Org_1', 'hasResource', 'Obs_1'],
        ['Org_1', 'hasResource', 'Obs_2'],
        ['Obs_2', 'hasSite', 'Sub_2'],
    ]
    assoc_list2 = [
        ['PS_1', 'hasDevice', 'PD_1'],
        ['IS_1', 'hasDevice', 'ID_1'],

        ['PD_1', 'hasDevice', 'ID_1'],
    ]

    def spy_get_child_sites(self, parent_site_id=None, org_id=None, exclude_types=None, include_parents=True, id_only=True):
        child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id=parent_site_id,
                                                                    org_id=org_id,
                                                                    exclude_types=exclude_types,
                                                                    include_parents=include_parents,
                                                                    id_only=id_only)

        print "child_sites of", parent_site_id, "are", child_sites
        print "site_ancestors of", parent_site_id, "are", site_ancestors

        return child_sites, site_ancestors

    def test_get_child_sites(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='Obs_1', include_parents=False, id_only=True)
        self.assertEquals(len(child_sites), 3)
        self.assertEquals(len(site_ancestors), 3)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('PS_1', child_sites)
        self.assertIn('IS_1', child_sites)
        self.assertNotIn('Obs_1', child_sites)
        self.assertEquals(len([v for v in child_sites.values() if v is None]), 3)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='Obs_1', include_parents=False, id_only=False)
        self.assertEquals(len(child_sites), 3)
        self.assertEquals(len(site_ancestors), 3)
        self.assertEquals(len([v for v in child_sites.values() if v is None]), 0)
        self.assertEquals(child_sites['Sub_1']._get_type(), RT.Subsite)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='Obs_1', include_parents=True)
        self.assertEquals(len(child_sites), 4)
        self.assertEquals(len(site_ancestors), 3)
        self.assertIn('Obs_1', child_sites)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='Sub_1', include_parents=False)
        self.assertEquals(len(child_sites), 2)
        self.assertEquals(len(site_ancestors), 2)
        self.assertNotIn('Sub_1', child_sites)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='Sub_1', include_parents=True)
        self.assertEquals(len(child_sites), 4)
        self.assertEquals(len(site_ancestors), 3)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('Obs_1', child_sites)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='PS_1', include_parents=False)
        self.assertEquals(len(child_sites), 1)
        self.assertEquals(len(site_ancestors), 1)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='PS_1', include_parents=True)
        self.assertEquals(len(child_sites), 4)
        self.assertEquals(len(site_ancestors), 3)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='IS_1', include_parents=False)
        self.assertEquals(len(child_sites), 0)
        self.assertEquals(len(site_ancestors), 0)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='IS_1', include_parents=True)
        self.assertEquals(len(child_sites), 4)
        self.assertEquals(len(site_ancestors), 3)

        child_sites, site_ancestors = self.spy_get_child_sites(parent_site_id='XXX', include_parents=True)
        self.assertEquals(len(child_sites), 1)
        self.assertEquals(len(site_ancestors), 0)

    def test_get_child_sites_org(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=False, id_only=True)
        self.assertEquals(len(child_sites), 6)
        self.assertEquals(len(site_ancestors), 5)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('PS_1', child_sites)
        self.assertIn('IS_1', child_sites)
        self.assertIn('Obs_1', child_sites)
        self.assertIn('Obs_2', child_sites)

        child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=True, id_only=True)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)

        child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=True, id_only=False)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)
        self.assertEquals(len([v for v in child_sites.values() if v is None]), 0)
        self.assertEquals(child_sites['Org_1']._get_type(), RT.Org)

    def test_get_site_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        site_devices = self.obs_util.get_site_devices(['Sub_1', 'PS_1', 'IS_1'])
        self.assertEquals(len(site_devices), 3)
        self.assertEquals(site_devices['Sub_1'], [])
        self.assertEquals(site_devices['IS_1'], [('InstrumentSite', 'ID_1', 'InstrumentDevice')])

    def test_get_child_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        child_devices = self.obs_util.get_child_devices('PD_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['PD_1'][0][1], 'ID_1')

        child_devices = self.obs_util.get_child_devices('ID_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['ID_1'], [])

        child_devices = self.obs_util.get_child_devices('Sub_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['Sub_1'], [])

        child_devices = self.obs_util.get_child_devices('XXX')
        self.assertEquals(len(child_devices), 1)

    event_list1 = [
        dict(et='DeviceStatusEvent', o='ID_1', attr=dict(status=DeviceStatusType.STATUS_WARNING) )
    ]
    event_list2 = [
        dict(et='DeviceStatusEvent', o='ID_1', attr=dict(status=DeviceStatusType.STATUS_WARNING))
    ]
    event_list3 = [
        dict(et='DeviceCommsEvent', o='ID_1', attr=dict(state=DeviceCommsType.DATA_DELIVERY_INTERRUPTION))
    ]
    event_list4 = [
        dict(et='DeviceStatusEvent', o='PD_1', attr=dict(status=DeviceStatusType.STATUS_WARNING)),
        dict(et='DeviceCommsEvent', o='PD_1', attr=dict(state=DeviceCommsType.DATA_DELIVERY_INTERRUPTION))
    ]

    def test_get_status_roll_ups(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 + self.assoc_list2)
        self.mu.load_mock_events(self.event_list1)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        # No problems
        status_rollups = self.obs_util.get_status_roll_ups('ID_1', RT.InstrumentDevice)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('PD_1', RT.PlatformDevice)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Sub_1')
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Obs_1')
        self._assert_status(status_rollups, 'Sub_1')
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        # ID_1 power warning
        self.mu.load_mock_events(self.event_list2)
        status_rollups = self.obs_util.get_status_roll_ups('ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups, 'ID_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('PD_1', RT.PlatformDevice)
        self._assert_status(status_rollups, 'PD_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('IS_1', RT.InstrumentSite)
        self.assertIn('IS_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('PS_1', RT.PlatformSite)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING)

        # ID_1 power+comms warning
        self.mu.load_mock_events(self.event_list3)
        status_rollups = self.obs_util.get_status_roll_ups('ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups, 'ID_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('PD_1', RT.PlatformDevice)
        self._assert_status(status_rollups, 'PD_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Sub_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Obs_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'Sub_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)

    def test_get_status_roll_ups_platform_warn(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 + self.assoc_list2)
        self.mu.load_mock_events(self.event_list4)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        # PD_1 power+comms warning
        status_rollups = self.obs_util.get_status_roll_ups('ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('PD_1', RT.PlatformDevice)
        #log.warn("status %s" % status_rollups)
        self._assert_status(status_rollups, 'PD_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Sub_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Obs_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'Sub_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PS_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1', agg=DeviceStatusType.STATUS_WARNING, power=DeviceStatusType.STATUS_WARNING, comms=DeviceStatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

    def _assert_status(self, status_rollups, res_id=None, agg=DeviceStatusType.STATUS_OK, loc=DeviceStatusType.STATUS_OK,
                       data=DeviceStatusType.STATUS_OK, comms=DeviceStatusType.STATUS_OK, power=DeviceStatusType.STATUS_OK):
        res_status = status_rollups[res_id] if res_id else status_rollups
        self.assertEquals(len(res_status), 5)
#        #self.assertEquals(res_status['agg'], agg)
#        self.assertEquals(res_status['loc'], loc)
#        self.assertEquals(res_status['data'], data)
#        self.assertEquals(res_status['comms'], comms)
#        self.assertEquals(res_status['power'], power)

    res_list1 = [
        dict(rt='DataProduct', _id='DP_1', attr={}),
        dict(rt='DataProduct', _id='DP_2', attr={}),
        dict(rt='DataProduct', _id='DP_3', attr={}),
        dict(rt='DataProduct', _id='DP_4', attr={}),
        dict(rt='DataProduct', _id='DP_5', attr={}),
        ]

    assoc_list3 = [
        ['DP_1', 'hasSource', 'ID_1'],
        ['DP_2', 'hasSource', 'ID_1'],
        ['DP_3', 'hasSource', 'ID_1'],
        ['DP_3', 'hasSource', 'PD_1'],
        ['DP_4', 'hasSource', 'PD_1'],
        ['DP_5', 'hasSource', 'PD_1'],
        ]

    def test_get_device_data_products(self):
        self.mu.load_mock_resources(self.res_list + self.res_list1)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 + self.assoc_list2 + self.assoc_list3)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        res_dict = self.obs_util.get_site_data_products('Obs_1', RT.Observatory)
        self.assertGreaterEqual(len(res_dict), 6)
        self.assertIsNone(res_dict['data_product_resources'])
        self.assertIn('ID_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['ID_1']), 3)
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])
        self.assertIn('PD_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['PD_1']), 3)

        res_dict = self.obs_util.get_site_data_products('PS_1', RT.PlatformSite)
        self.assertEquals(len(res_dict['device_data_products']['ID_1']), 3)
        self.assertIn('ID_1', res_dict['device_data_products'])
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])
        self.assertIn('PD_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['PD_1']), 3)

        res_dict = self.obs_util.get_site_data_products('Org_1', RT.Org)
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])

        res_dict = self.obs_util.get_site_data_products('PS_1', RT.PlatformSite, include_data_products=True)
        self.assertIsNotNone(res_dict['data_product_resources'])
        self.assertIn('DP_1', res_dict['data_product_resources'])
示例#4
0
class DeploymentPlanner(object):
    """
    A deployment activator validates that a set of devices will map to a set of sites in one unique way

    its primary purpose is to prepare( ) after which you'll be able to access what associations must be made (and unmade)

    """

    def __init__(self, clients=None, enhanced_rr=None):
        self.clients = clients
        self.enhanced_rr = enhanced_rr

        if not enhanced_rr:
            self.enhanced_rr = EnhancedResourceRegistryClient(self.clients.resource_registry)
        self.outil = ObservatoryUtil(self, enhanced_rr=self.enhanced_rr)

        #self.resource_collector= DeploymentResourceCollector(self.clients, self.enhanced_rr)
        #self.resource_collector = resource_collector.create(self.deployment_obj)

    def _find_top_site_device(self, deployment_id):
        top_site = ''
        top_device = ''
        #retrieve the site tree information using the OUTIL functions; site info as well has site children
        deploy_items_objs, _ = self.clients.resource_registry.find_subjects(predicate=PRED.hasDeployment, object=deployment_id, id_only=False)
        log.debug("site_ids associated to this deployment: %s", deploy_items_objs)
        for obj in deploy_items_objs:
            rsrc_type = obj.type_
            log.debug("resource type associated to this deployment:: %s", rsrc_type)
            if RT.PlatformDevice == rsrc_type or RT.InstrumentDevice == rsrc_type:
                top_device = obj
            elif RT.PlatformSite == rsrc_type or RT.InstrumentSite == rsrc_type:
                top_site = obj
            else:
                log.error('Deployment may only link to devices and sites. Deployment: %s', str(self.deployment_obj))

        if not top_device or not top_site:
            log.error('Deployment must associate to both site and device. Deployment: %s', str(self.deployment_obj))
            raise BadRequest('Deployment must associate to both site and device. Deployment: %s', str(self.deployment_obj))

        return top_site, top_device


    def _find_pairs_to_remove(self):
        #figure out if any of the devices in the new mapping are already mapped and need to be removed
        pairs_to_remove = []
        pairs_to_ignore = []
        for (s, d) in self.match_list:
            rm_pair, ignore_pair = self._find_existing_relationship(s, d)
            if rm_pair:
                pairs_to_remove.append(rm_pair)
            if ignore_pair:
                pairs_to_ignore.append(ignore_pair)

        log.info("Pairs to ignore (will be removed from add list): %s", pairs_to_ignore)

        # make sure that anything being removed is not also being added
        self.match_list = filter(lambda x: x not in pairs_to_ignore, self.match_list)

        log.info("Pairs to remove: %s", pairs_to_remove)
        self.remove_list = pairs_to_remove


    def _find_existing_relationship(self, site_id, device_id, site_type=None, device_type=None):
        # look for an existing relationship between the site_id and another device.
        # if this site/device pair already exists, we leave it alone
        assert(type("") == type(site_id) == type(device_id))

        log.debug("checking %s/%s pair for deployment", site_type, device_type)
        #return a pair that should be REMOVED, or None

        if site_type is None and site_id in self.site_resources:
            site_type = self.site_resources[site_id].type_

        if device_type is None and device_id in self.device_resources:
            device_type = self.device_resources[device_id].type_

        log.debug("checking existing %s hasDevice %s links", site_type, device_type)

        ret_remove = None
        ret_ignore = None

        try:
            found_device_id = self.enhanced_rr.find_object(site_id, PRED.hasDevice, device_type, True)

            if found_device_id == device_id:
                ret_ignore = (site_id, device_id)
            else:
                ret_remove = (site_id, found_device_id)
                log.warning("%s '%s' already hasDevice %s", site_type, site_id, device_type)

        except NotFound:
            pass

        return ret_remove, ret_ignore


    def _get_site_ref_designator_map(self):
        # create a map of site ids to their reference designator codes to facilitate matching
        site_ref_designator_map = {}
        for id, site_obj in self.site_resources.iteritems():
            site_ref_designator_map[site_obj.reference_designator] = id
        log.debug("prepare_activation site_ref_designator_map: %s", site_ref_designator_map)
        return site_ref_designator_map


    def _get_device_resources(self, device_tree):
        # create a map of device ids to their full resource object to assit with lookup and validation
        device_objs = self.clients.resource_registry.read_mult(device_tree.keys())
        log.debug("prepare_activation device_objectss: %s", device_objs)
        for device_obj in device_objs:
            self.device_resources[device_obj._id] = device_obj


    def _get_models(self):
        # retrieve all hasModel associations from the registry then filter
        models_tuples = {}
        assoc_list = self.outil._get_predicate_assocs(PRED.hasModel)
        for assoc in assoc_list:
            # only include these subject types in the map
            if assoc.st in [RT.InstrumentDevice, RT.InstrumentSite, RT.PlatformDevice, RT.PlatformSite]:
                if assoc.s not in models_tuples:
                    models_tuples[assoc.s] = []
                # a site may support more than one model so map to a list of models
                models_tuples[assoc.s].append((assoc.st, assoc.o, assoc.ot))
                if assoc.s not in self.models_map:
                    self.models_map[assoc.s] = []
                self.models_map[assoc.s].append(assoc.o)
        log.debug("models_map: %s", self.models_map )


    def _validate_models(self, site_id, device_id):
        # validate that the device and the site models are compatible
        if device_id in self.models_map:
            device_model_list = self.models_map[device_id]
            # devices should only be associated to one model
            if len(device_model_list) != 1:
                log.error("Device not associated to one distinct model. Device id: %s", device_id)

            elif  device_model_list and device_model_list[0] not in  self.models_map[site_id]:
                log.error("Device and Site to not share a compatible model. Device id: %s   Site id: %s", site_id)
        else:
            log.error("Device not associated with a device model. Device id: %s", device_id)
            raise NotFound("Device not associated with a device model. Device id: %s", device_id)


    def _validate_port_assignments(self, device_id, platform_port):
        deployment_context_type = type(self.deployment_obj.context).__name__

        self._validate_ooi_reference_designator(device_id, platform_port)

        # a one-to-one deployment of a device onto an RSN platform
        if OT.CabledInstrumentDeploymentContext == deployment_context_type or \
            OT.CabledNodeDeploymentContext == deployment_context_type:

            # validate IP address for a cabled node deployment
            from socket import inet_aton
            try:
                inet_aton(platform_port.ip_address)
            except :
                log.error('IP address validation failed for device. Device id: %s', device_id)

        # validate port_type based on deployment context
        # a platform device deployment should have UPLINK port type
        if OT.RemotePlatformDeploymentContext == deployment_context_type or \
            OT.CabledNodeDeploymentContext == deployment_context_type:
            if device_id in self.device_resources and self.device_resources[device_id].type_ is RT.PlatformDevice:
                if platform_port.port_type != PortTypeEnum.UPLINK:
                    log.warning('Type of port for platform port assignment should be UPLINK.  Device id: %s', device_id)

        #validate that parent_id is provided
        if not platform_port.parent_id:
            log.warning('Id of parent device should be provided in port assignment information. Device id: %s', device_id)


    def _validate_ooi_reference_designator(self, device_id, device_port):
        ooi_rd = OOIReferenceDesignator(device_port.reference_designator)
        if ooi_rd.error:
           log.warning("Invalid OOIReferenceDesignator ( %s ) specified for device %s", device_port.reference_designator, device_id)
        if not ooi_rd.port:
            log.warning("Invalid OOIReferenceDesignator ( %s ) specified for device %s, could not retrieve port", device_port.reference_designator, device_id)


    def get_deployment_sites_devices(self, deployment_obj):
        # retrieve all site and device ids related to this deployment
        site_ids = []
        device_ids = []
        self.outil = ObservatoryUtil(self, enhanced_rr=self.enhanced_rr)

        top_site, top_device = self._find_top_site_device(deployment_obj._id)

        site_resources, site_children = self.outil.get_child_sites( parent_site_id=top_site._id, id_only=False)
        site_ids = site_resources.keys()

        # get_site_devices returns a tuple that includes all devices linked to deployment sites
        site_devices = self.outil.get_site_devices(site_ids)
        for site, tuple_list in site_devices.iteritems():
            for (site_type, device_id, device_type) in tuple_list:
                device_ids.append(device_id)

        return site_ids, device_ids


    def prepare_activation(self, deployment_obj):
        """
        Prepare (validate) a deployment for activation, returning lists of what associations need to be added
        and which ones need to be removed.
        """

        self.match_list = []
        self.remove_list = []
        self.unmatched_device_list = []

        self.models_map = {}

        self.top_device = ''
        self.top_site = ''
        self.deployment_obj = deployment_obj
        self.site_resources = {}
        self.device_resources = {}

        self.outil = ObservatoryUtil(self, enhanced_rr=self.enhanced_rr)

        # retrieve the site tree information using the OUTIL functions; site info as well has site children
        self.top_site, self.top_device = self._find_top_site_device(deployment_obj._id)
        # must have a site and a device to continue
        if not self.top_site or not self.top_device:
            return [], []

        log.debug("port_assignments: %s", self.deployment_obj.port_assignments )

        # retrieve all models to use in match validation
        self._get_models()

        self.site_resources, site_children = self.outil.get_child_sites( parent_site_id=self.top_site._id, id_only=False)

        log.debug("site_resources: %s", self.site_resources)
        log.debug("site_children: %s", site_children)

        site_ref_designator_map = self._get_site_ref_designator_map()

        # retrieve the device tree from outil then cache the device resources
        device_tree = self.outil.get_child_devices(device_id=self.top_device._id)
        self._get_device_resources(device_tree)

        def _match_devices(device_id):

            # there will not be a port assignment for the top device
            if device_id == self.top_device._id:
                self._validate_models(self.top_site._id, self.top_device._id)
                self.match_list.append((self.top_site._id, self.top_device._id))

            tuple_list = device_tree[device_id]

            for (pt, child_id, ct) in tuple_list:
                log.debug("  tuple  - pt: %s  child_id: %s  ct: %s", pt, child_id, ct)

                # match this child device then if it has children, call _match_devices with this id

                # check that this device is represented in device tree and in port assignments
                if child_id in self.device_resources and child_id in self.deployment_obj.port_assignments:
                    platform_port = self.deployment_obj.port_assignments[child_id]
                    log.debug("device platform_port: %s", platform_port)

                    # validate PlatformPort info for this device
                    self._validate_port_assignments(child_id, platform_port)

                    if platform_port.reference_designator in site_ref_designator_map:
                        matched_site = site_ref_designator_map[platform_port.reference_designator]
                        self._validate_models(matched_site, child_id)
                        log.info("match_list append site: %s  device: %s", matched_site, child_id)
                        self.match_list.append((matched_site, child_id))

                        #recurse on the children of this device
                        _match_devices(child_id)

                # otherwise cant be matched to a site
                else:
                    self.unmatched_device_list.append(child_id)

        _match_devices(self.top_device._id)

        # check for hasDevice relations to remove and existing hasDevice relations
        self. _find_pairs_to_remove()

        if self.unmatched_device_list:
            log.warning("Devices not matched to sites: %s  ", self.unmatched_device_list)

        return self.remove_list, self.match_list
class TestObservatoryUtil(IonUnitTestCase):
    def setUp(self):
        self.mu = MockUtil()
        self.process_mock = self.mu.create_process_mock()
        self.container_mock = self.mu.create_container_mock()
        self.dsm_mock = self.mu.create_device_status_manager_mock()

    res_list = [
        dict(rt='Org', _id='Org_1', attr={}),
        dict(rt='Observatory', _id='Obs_1', attr={}),
        dict(rt='Observatory', _id='Obs_2', attr={}),
        dict(rt='Subsite', _id='Sub_1', attr={}),
        dict(rt='Subsite', _id='Sub_2', attr={}),
        dict(rt='PlatformSite', _id='PS_1', attr={}),
        dict(rt='InstrumentSite', _id='IS_1', attr={}),
        dict(rt='PlatformDevice', _id='PD_1', attr={}),
        dict(rt='InstrumentDevice', _id='ID_1', attr={}),
    ]

    assoc_list = [
        ['Obs_1', 'hasSite', 'Sub_1'],
        ['Sub_1', 'hasSite', 'PS_1'],
        ['PS_1', 'hasSite', 'IS_1'],
    ]
    assoc_list1 = [
        ['Org_1', 'hasResource', 'Obs_1'],
        ['Org_1', 'hasResource', 'Obs_2'],
        ['Obs_2', 'hasSite', 'Sub_2'],
    ]
    assoc_list2 = [
        ['PS_1', 'hasDevice', 'PD_1'],
        ['IS_1', 'hasDevice', 'ID_1'],
        ['PD_1', 'hasDevice', 'ID_1'],
    ]

    def spy_get_child_sites(self,
                            parent_site_id=None,
                            org_id=None,
                            exclude_types=None,
                            include_parents=True,
                            id_only=True):
        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id=parent_site_id,
            org_id=org_id,
            exclude_types=exclude_types,
            include_parents=include_parents,
            id_only=id_only)

        print "child_sites of", parent_site_id, "are", child_sites
        print "site_ancestors of", parent_site_id, "are", site_ancestors

        return child_sites, site_ancestors

    def test_get_child_sites(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Obs_1', include_parents=False, id_only=True)
        self.assertEquals(len(site_resources), 3)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Sub_1', site_resources)
        self.assertIn('PS_1', site_resources)
        self.assertIn('IS_1', site_resources)
        self.assertNotIn('Obs_1', site_resources)
        self.assertEquals(
            len([v for v in site_resources.values() if v is None]), 3)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Obs_1', include_parents=False, id_only=False)
        self.assertEquals(len(site_resources), 3)
        self.assertEquals(len(site_children), 3)
        self.assertEquals(
            len([v for v in site_resources.values() if v is None]), 0)
        self.assertEquals(site_resources['Sub_1']._get_type(), RT.Subsite)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Obs_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Obs_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Sub_1', include_parents=False)
        self.assertEquals(len(site_resources), 2)
        self.assertEquals(len(site_children), 2)
        self.assertNotIn('Sub_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Sub_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Sub_1', site_resources)
        self.assertIn('Obs_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='PS_1', include_parents=False)
        self.assertEquals(len(site_resources), 1)
        self.assertEquals(len(site_children), 1)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='PS_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='IS_1', include_parents=False)
        self.assertEquals(len(site_resources), 0)
        self.assertEquals(len(site_children), 0)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='IS_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='XXX', include_parents=True)
        self.assertEquals(len(site_resources), 1)
        self.assertEquals(len(site_children), 0)

    def test_get_child_sites_org(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=False, id_only=True)
        self.assertEquals(len(child_sites), 6)
        self.assertEquals(len(site_ancestors), 5)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('PS_1', child_sites)
        self.assertIn('IS_1', child_sites)
        self.assertIn('Obs_1', child_sites)
        self.assertIn('Obs_2', child_sites)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=True, id_only=True)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=True, id_only=False)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)
        self.assertEquals(len([v for v in child_sites.values() if v is None]),
                          0)
        self.assertEquals(child_sites['Org_1']._get_type(), RT.Org)

    def test_get_site_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        site_devices = self.obs_util.get_site_devices(
            ['Sub_1', 'PS_1', 'IS_1'])
        self.assertEquals(len(site_devices), 3)
        self.assertEquals(site_devices['Sub_1'], [])
        self.assertEquals(site_devices['IS_1'],
                          [('InstrumentSite', 'ID_1', 'InstrumentDevice')])

    def test_get_child_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        child_devices = self.obs_util.get_child_devices('PD_1')
        self.assertEquals(len(child_devices), 2)
        self.assertEquals(child_devices['PD_1'][0][1], 'ID_1')

        child_devices = self.obs_util.get_child_devices('ID_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['ID_1'], [])

        child_devices = self.obs_util.get_child_devices('Sub_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['Sub_1'], [])

        child_devices = self.obs_util.get_child_devices('XXX')
        self.assertEquals(len(child_devices), 1)

    def test_get_device_data_products(self):
        self.mu.load_mock_resources(self.res_list + self.res_list1)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 +
                                       self.assoc_list2 + self.assoc_list3)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        res_dict = self.obs_util.get_site_data_products(
            'Obs_1', RT.Observatory)
        self.assertGreaterEqual(len(res_dict), 6)
        self.assertIsNone(res_dict['data_product_resources'])
        self.assertIn('ID_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['ID_1']), 3)
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])
        self.assertIn('PD_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['PD_1']), 3)

        res_dict = self.obs_util.get_site_data_products(
            'PS_1', RT.PlatformSite)
        self.assertEquals(len(res_dict['device_data_products']['ID_1']), 3)
        self.assertIn('ID_1', res_dict['device_data_products'])
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])
        self.assertIn('PD_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['PD_1']), 3)

        res_dict = self.obs_util.get_site_data_products('Org_1', RT.Org)
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])

        res_dict = self.obs_util.get_site_data_products(
            'PS_1', RT.PlatformSite, include_data_products=True)
        self.assertIsNotNone(res_dict['data_product_resources'])
        self.assertIn('DP_1', res_dict['data_product_resources'])

        #import pprint
        #pprint.pprint(res_dict)

    status_by_device_1 = {
        "ID_1":
        _devstat("ID_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK,
                 DST.STATUS_OK),
        "PD_1":
        _devstat("PD_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK,
                 DST.STATUS_OK),
    }
    status_by_device_2 = {
        "ID_1":
        _devstat("ID_1", DST.STATUS_WARNING, DST.STATUS_OK, DST.STATUS_OK,
                 DST.STATUS_OK),
        "PD_1":
        _devstat("PD_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK,
                 DST.STATUS_OK),
    }
    status_by_device_3 = {
        "ID_1":
        _devstat("ID_1", DST.STATUS_WARNING, DST.STATUS_WARNING, DST.STATUS_OK,
                 DST.STATUS_OK),
        "PD_1":
        _devstat("PD_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK,
                 DST.STATUS_OK),
    }
    status_by_device_4 = {
        "ID_1":
        _devstat("ID_1", DST.STATUS_OK, DST.STATUS_OK, DST.STATUS_OK,
                 DST.STATUS_OK),
        "PD_1":
        _devstat("PD_1", DST.STATUS_WARNING, DST.STATUS_WARNING, DST.STATUS_OK,
                 DST.STATUS_OK),
    }

    def test_get_status_roll_ups(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 +
                                       self.assoc_list2)
        self.mu.load_mock_device_statuses(self.status_by_device_1)

        self.obs_util = ObservatoryUtil(self.process_mock,
                                        self.container_mock,
                                        device_status_mgr=self.dsm_mock)

        # No problems
        status_rollups = self.obs_util.get_status_roll_ups(
            'ID_1', RT.InstrumentDevice)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'PD_1', RT.PlatformDevice)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Sub_1')
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Obs_1')
        self._assert_status(status_rollups, 'Sub_1')
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        # ID_1 power warning
        self.mu.load_mock_device_statuses(self.status_by_device_2)
        status_rollups = self.obs_util.get_status_roll_ups(
            'ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'PD_1', RT.PlatformDevice)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'IS_1', RT.InstrumentSite)
        self.assertIn('IS_1', status_rollups)
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'PS_1', RT.PlatformSite)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING)

        # ID_1 power+comms warning
        self.mu.load_mock_device_statuses(self.status_by_device_3)
        status_rollups = self.obs_util.get_status_roll_ups(
            'ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'PD_1', RT.PlatformDevice)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'Sub_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'Obs_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'Sub_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)

    def test_get_status_roll_ups_platform_warn(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 +
                                       self.assoc_list2)
        self.mu.load_mock_device_statuses(self.status_by_device_4)

        self.obs_util = ObservatoryUtil(self.process_mock,
                                        self.container_mock,
                                        device_status_mgr=self.dsm_mock)

        # PD_1 power+comms warning
        status_rollups = self.obs_util.get_status_roll_ups(
            'ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'PD_1', RT.PlatformDevice)
        #log.warn("status %s" % status_rollups)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'Sub_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'Obs_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'Sub_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=DST.STATUS_WARNING,
                            power=DST.STATUS_WARNING,
                            comms=DST.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

    def _assert_status(self,
                       status_rollups,
                       res_id=None,
                       agg=DST.STATUS_OK,
                       loc=DST.STATUS_OK,
                       data=DST.STATUS_OK,
                       comms=DST.STATUS_OK,
                       power=DST.STATUS_OK):
        res_status = status_rollups[res_id] if res_id else status_rollups
        log.debug("_assert_status(%s) = %s", res_id, res_status)
        self.assertEquals(len(res_status), 5)
        if agg is not None:
            self.assertEquals(res_status['agg'], agg)
        if loc is not None:
            self.assertEquals(
                res_status[AggregateStatusType.AGGREGATE_LOCATION], loc)
        if data is not None:
            self.assertEquals(res_status[AggregateStatusType.AGGREGATE_DATA],
                              data)
        if comms is not None:
            self.assertEquals(res_status[AggregateStatusType.AGGREGATE_COMMS],
                              comms)
        if power is not None:
            self.assertEquals(res_status[AggregateStatusType.AGGREGATE_POWER],
                              power)

    res_list1 = [
        dict(rt='DataProduct', _id='DP_1', attr={}),
        dict(rt='DataProduct', _id='DP_2', attr={}),
        dict(rt='DataProduct', _id='DP_3', attr={}),
        dict(rt='DataProduct', _id='DP_4', attr={}),
        dict(rt='DataProduct', _id='DP_5', attr={}),
    ]

    assoc_list3 = [
        ['DP_1', 'hasSource', 'ID_1'],
        ['DP_1', 'hasSource', 'IS_1'],
        ['DP_2', 'hasSource', 'ID_1'],
        ['DP_3', 'hasSource', 'ID_1'],
        ['DP_3', 'hasSource', 'PD_1'],
        ['DP_4', 'hasSource', 'PD_1'],
        ['DP_5', 'hasSource', 'PD_1'],
    ]
示例#6
0
class TestObservatoryUtil(IonUnitTestCase):
    def setUp(self):
        self.mu = MockUtil()
        self.process_mock = self.mu.create_process_mock()
        self.container_mock = self.mu.create_container_mock()

    res_list = [
        dict(rt='Org', _id='Org_1', attr={}),
        dict(rt='Observatory', _id='Obs_1', attr={}),
        dict(rt='Observatory', _id='Obs_2', attr={}),
        dict(rt='Subsite', _id='Sub_1', attr={}),
        dict(rt='Subsite', _id='Sub_2', attr={}),
        dict(rt='PlatformSite', _id='PS_1', attr={}),
        dict(rt='InstrumentSite', _id='IS_1', attr={}),
        dict(rt='PlatformDevice', _id='PD_1', attr={}),
        dict(rt='InstrumentDevice', _id='ID_1', attr={}),
    ]

    assoc_list = [
        ['Obs_1', 'hasSite', 'Sub_1'],
        ['Sub_1', 'hasSite', 'PS_1'],
        ['PS_1', 'hasSite', 'IS_1'],
    ]
    assoc_list1 = [
        ['Org_1', 'hasResource', 'Obs_1'],
        ['Org_1', 'hasResource', 'Obs_2'],
        ['Obs_2', 'hasSite', 'Sub_2'],
    ]
    assoc_list2 = [
        ['PS_1', 'hasDevice', 'PD_1'],
        ['IS_1', 'hasDevice', 'ID_1'],
        ['PD_1', 'hasDevice', 'ID_1'],
    ]

    def spy_get_child_sites(self,
                            parent_site_id=None,
                            org_id=None,
                            exclude_types=None,
                            include_parents=True,
                            id_only=True):
        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id=parent_site_id,
            org_id=org_id,
            exclude_types=exclude_types,
            include_parents=include_parents,
            id_only=id_only)

        print "child_sites of", parent_site_id, "are", child_sites
        print "site_ancestors of", parent_site_id, "are", site_ancestors

        return child_sites, site_ancestors

    def test_get_child_sites(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Obs_1', include_parents=False, id_only=True)
        self.assertEquals(len(site_resources), 3)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Sub_1', site_resources)
        self.assertIn('PS_1', site_resources)
        self.assertIn('IS_1', site_resources)
        self.assertNotIn('Obs_1', site_resources)
        self.assertEquals(
            len([v for v in site_resources.values() if v is None]), 3)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Obs_1', include_parents=False, id_only=False)
        self.assertEquals(len(site_resources), 3)
        self.assertEquals(len(site_children), 3)
        self.assertEquals(
            len([v for v in site_resources.values() if v is None]), 0)
        self.assertEquals(site_resources['Sub_1']._get_type(), RT.Subsite)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Obs_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Obs_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Sub_1', include_parents=False)
        self.assertEquals(len(site_resources), 2)
        self.assertEquals(len(site_children), 2)
        self.assertNotIn('Sub_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='Sub_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)
        self.assertIn('Sub_1', site_resources)
        self.assertIn('Obs_1', site_resources)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='PS_1', include_parents=False)
        self.assertEquals(len(site_resources), 1)
        self.assertEquals(len(site_children), 1)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='PS_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='IS_1', include_parents=False)
        self.assertEquals(len(site_resources), 0)
        self.assertEquals(len(site_children), 0)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='IS_1', include_parents=True)
        self.assertEquals(len(site_resources), 4)
        self.assertEquals(len(site_children), 3)

        site_resources, site_children = self.spy_get_child_sites(
            parent_site_id='XXX', include_parents=True)
        self.assertEquals(len(site_resources), 1)
        self.assertEquals(len(site_children), 0)

    def test_get_child_sites_org(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=False, id_only=True)
        self.assertEquals(len(child_sites), 6)
        self.assertEquals(len(site_ancestors), 5)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('PS_1', child_sites)
        self.assertIn('IS_1', child_sites)
        self.assertIn('Obs_1', child_sites)
        self.assertIn('Obs_2', child_sites)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=True, id_only=True)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=True, id_only=False)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)
        self.assertEquals(len([v for v in child_sites.values() if v is None]),
                          0)
        self.assertEquals(child_sites['Org_1']._get_type(), RT.Org)

    def test_get_site_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        site_devices = self.obs_util.get_site_devices(
            ['Sub_1', 'PS_1', 'IS_1'])
        self.assertEquals(len(site_devices), 3)
        self.assertEquals(site_devices['Sub_1'], [])
        self.assertEquals(site_devices['IS_1'],
                          [('InstrumentSite', 'ID_1', 'InstrumentDevice')])

    def test_get_child_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        child_devices = self.obs_util.get_child_devices('PD_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['PD_1'][0][1], 'ID_1')

        child_devices = self.obs_util.get_child_devices('ID_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['ID_1'], [])

        child_devices = self.obs_util.get_child_devices('Sub_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['Sub_1'], [])

        child_devices = self.obs_util.get_child_devices('XXX')
        self.assertEquals(len(child_devices), 1)

    event_list1 = [
        dict(et='DeviceStatusEvent',
             o='ID_1',
             attr=dict(status=DeviceStatusType.STATUS_WARNING))
    ]
    event_list2 = [
        dict(et='DeviceStatusEvent',
             o='ID_1',
             attr=dict(status=DeviceStatusType.STATUS_WARNING))
    ]
    event_list3 = [
        dict(et='DeviceCommsEvent',
             o='ID_1',
             attr=dict(state=DeviceCommsType.DATA_DELIVERY_INTERRUPTION))
    ]
    event_list4 = [
        dict(et='DeviceStatusEvent',
             o='PD_1',
             attr=dict(status=DeviceStatusType.STATUS_WARNING)),
        dict(et='DeviceCommsEvent',
             o='PD_1',
             attr=dict(state=DeviceCommsType.DATA_DELIVERY_INTERRUPTION))
    ]

    def _assert_status(self,
                       status_rollups,
                       res_id=None,
                       agg=DeviceStatusType.STATUS_OK,
                       loc=DeviceStatusType.STATUS_OK,
                       data=DeviceStatusType.STATUS_OK,
                       comms=DeviceStatusType.STATUS_OK,
                       power=DeviceStatusType.STATUS_OK):
        res_status = status_rollups[res_id] if res_id else status_rollups
        self.assertEquals(len(res_status), 5)
#        #self.assertEquals(res_status['agg'], agg)
#        self.assertEquals(res_status['loc'], loc)
#        self.assertEquals(res_status['data'], data)
#        self.assertEquals(res_status['comms'], comms)
#        self.assertEquals(res_status['power'], power)

    res_list1 = [
        dict(rt='DataProduct', _id='DP_1', attr={}),
        dict(rt='DataProduct', _id='DP_2', attr={}),
        dict(rt='DataProduct', _id='DP_3', attr={}),
        dict(rt='DataProduct', _id='DP_4', attr={}),
        dict(rt='DataProduct', _id='DP_5', attr={}),
    ]

    assoc_list3 = [
        ['DP_1', 'hasSource', 'ID_1'],
        ['DP_2', 'hasSource', 'ID_1'],
        ['DP_3', 'hasSource', 'ID_1'],
        ['DP_3', 'hasSource', 'PD_1'],
        ['DP_4', 'hasSource', 'PD_1'],
        ['DP_5', 'hasSource', 'PD_1'],
    ]

    def test_get_device_data_products(self):
        self.mu.load_mock_resources(self.res_list + self.res_list1)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 +
                                       self.assoc_list2 + self.assoc_list3)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        res_dict = self.obs_util.get_site_data_products(
            'Obs_1', RT.Observatory)
        self.assertGreaterEqual(len(res_dict), 6)
        self.assertIsNone(res_dict['data_product_resources'])
        self.assertIn('ID_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['ID_1']), 3)
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])
        self.assertIn('PD_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['PD_1']), 3)

        res_dict = self.obs_util.get_site_data_products(
            'PS_1', RT.PlatformSite)
        self.assertEquals(len(res_dict['device_data_products']['ID_1']), 3)
        self.assertIn('ID_1', res_dict['device_data_products'])
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])
        self.assertIn('PD_1', res_dict['device_data_products'])
        self.assertEquals(len(res_dict['device_data_products']['PD_1']), 3)

        res_dict = self.obs_util.get_site_data_products('Org_1', RT.Org)
        self.assertIn('DP_1', res_dict['device_data_products']['ID_1'])

        res_dict = self.obs_util.get_site_data_products(
            'PS_1', RT.PlatformSite, include_data_products=True)
        self.assertIsNotNone(res_dict['data_product_resources'])
        self.assertIn('DP_1', res_dict['data_product_resources'])
示例#7
0
class TestObservatoryUtil(unittest.TestCase):
    def setUp(self):
        self.mu = MockUtil()
        self.process_mock = self.mu.create_process_mock()
        self.container_mock = self.mu.create_container_mock()

    res_list = [
        dict(rt='Org', _id='Org_1', attr={}),
        dict(rt='Observatory', _id='Obs_1', attr={}),
        dict(rt='Observatory', _id='Obs_2', attr={}),
        dict(rt='Subsite', _id='Sub_1', attr={}),
        dict(rt='Subsite', _id='Sub_2', attr={}),
        dict(rt='PlatformSite', _id='PS_1', attr={}),
        dict(rt='InstrumentSite', _id='IS_1', attr={}),
        dict(rt='PlatformDevice', _id='PD_1', attr={}),
        dict(rt='InstrumentDevice', _id='ID_1', attr={}),
    ]

    assoc_list = [
        ['Obs_1', 'hasSite', 'Sub_1'],
        ['Sub_1', 'hasSite', 'PS_1'],
        ['PS_1', 'hasSite', 'IS_1'],
    ]
    assoc_list1 = [
        ['Org_1', 'hasResource', 'Obs_1'],
        ['Org_1', 'hasResource', 'Obs_2'],
        ['Obs_2', 'hasSite', 'Sub_2'],
    ]
    assoc_list2 = [
        ['PS_1', 'hasDevice', 'PD_1'],
        ['IS_1', 'hasDevice', 'ID_1'],
        ['PD_1', 'hasDevice', 'ID_1'],
    ]

    def test_get_child_sites(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='Obs_1', include_parents=False, id_only=True)
        self.assertEquals(len(child_sites), 3)
        self.assertEquals(len(site_ancestors), 3)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('PS_1', child_sites)
        self.assertIn('IS_1', child_sites)
        self.assertNotIn('Obs_1', child_sites)
        self.assertEquals(len([v for v in child_sites.values() if v is None]),
                          3)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='Obs_1', include_parents=False, id_only=False)
        self.assertEquals(len(child_sites), 3)
        self.assertEquals(len(site_ancestors), 3)
        self.assertEquals(len([v for v in child_sites.values() if v is None]),
                          0)
        self.assertEquals(child_sites['Sub_1']._get_type(), RT.Subsite)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='Obs_1', include_parents=True)
        self.assertEquals(len(child_sites), 4)
        self.assertEquals(len(site_ancestors), 3)
        self.assertIn('Obs_1', child_sites)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='Sub_1', include_parents=False)
        self.assertEquals(len(child_sites), 2)
        self.assertEquals(len(site_ancestors), 2)
        self.assertNotIn('Sub_1', child_sites)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='Sub_1', include_parents=True)
        self.assertEquals(len(child_sites), 4)
        self.assertEquals(len(site_ancestors), 3)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('Obs_1', child_sites)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='PS_1', include_parents=False)
        self.assertEquals(len(child_sites), 1)
        self.assertEquals(len(site_ancestors), 1)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='PS_1', include_parents=True)
        self.assertEquals(len(child_sites), 4)
        self.assertEquals(len(site_ancestors), 3)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='IS_1', include_parents=False)
        self.assertEquals(len(child_sites), 0)
        self.assertEquals(len(site_ancestors), 0)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='IS_1', include_parents=True)
        self.assertEquals(len(child_sites), 4)
        self.assertEquals(len(site_ancestors), 3)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            parent_site_id='XXX', include_parents=True)
        self.assertEquals(len(child_sites), 1)
        self.assertEquals(len(site_ancestors), 0)

    def test_get_child_sites_org(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1)

        self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=False, id_only=True)
        self.assertEquals(len(child_sites), 6)
        self.assertEquals(len(site_ancestors), 5)
        self.assertIn('Sub_1', child_sites)
        self.assertIn('PS_1', child_sites)
        self.assertIn('IS_1', child_sites)
        self.assertIn('Obs_1', child_sites)
        self.assertIn('Obs_2', child_sites)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=True, id_only=True)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)

        child_sites, site_ancestors = self.obs_util.get_child_sites(
            org_id='Org_1', include_parents=True, id_only=False)
        self.assertEquals(len(child_sites), 7)
        self.assertEquals(len(site_ancestors), 5)
        self.assertEquals(len([v for v in child_sites.values() if v is None]),
                          0)
        self.assertEquals(child_sites['Org_1']._get_type(), RT.Org)

    def test_get_site_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        site_devices = self.obs_util.get_site_devices(
            ['Sub_1', 'PS_1', 'IS_1'])
        self.assertEquals(len(site_devices), 3)
        self.assertEquals(site_devices['Sub_1'], None)
        self.assertEquals(site_devices['IS_1'],
                          ('InstrumentSite', 'ID_1', 'InstrumentDevice'))

    def test_get_child_devices(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list2)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
        child_devices = self.obs_util.get_child_devices('PD_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['PD_1'][0][1], 'ID_1')

        child_devices = self.obs_util.get_child_devices('ID_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['ID_1'], [])

        child_devices = self.obs_util.get_child_devices('Sub_1')
        self.assertEquals(len(child_devices), 1)
        self.assertEquals(child_devices['Sub_1'], [])

        child_devices = self.obs_util.get_child_devices('XXX')
        self.assertEquals(len(child_devices), 1)

    event_list1 = [
        dict(et='DeviceStatusEvent',
             o='ID_1',
             attr=dict(state=DeviceStatusType.OK))
    ]
    event_list2 = [
        dict(et='DeviceStatusEvent',
             o='ID_1',
             attr=dict(state=DeviceStatusType.OUT_OF_RANGE))
    ]
    event_list3 = [
        dict(et='DeviceCommsEvent',
             o='ID_1',
             attr=dict(state=DeviceCommsType.DATA_DELIVERY_INTERRUPTION))
    ]
    event_list4 = [
        dict(et='DeviceStatusEvent',
             o='PD_1',
             attr=dict(state=DeviceStatusType.OUT_OF_RANGE)),
        dict(et='DeviceCommsEvent',
             o='PD_1',
             attr=dict(state=DeviceCommsType.DATA_DELIVERY_INTERRUPTION))
    ]

    def test_get_status_roll_ups(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 +
                                       self.assoc_list2)
        self.mu.load_mock_events(self.event_list1)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        # No problems
        status_rollups = self.obs_util.get_status_roll_ups(
            'ID_1', RT.InstrumentDevice)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'PD_1', RT.PlatformDevice)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Sub_1')
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'Obs_1')
        self._assert_status(status_rollups, 'Sub_1')
        self._assert_status(status_rollups, 'PS_1')
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        # ID_1 power warning
        self.mu.load_mock_events(self.event_list2)
        status_rollups = self.obs_util.get_status_roll_ups(
            'ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'PD_1', RT.PlatformDevice)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'IS_1', RT.InstrumentSite)
        self.assertIn('IS_1', status_rollups)
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'PS_1', RT.PlatformSite)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING)

        # ID_1 power+comms warning
        self.mu.load_mock_events(self.event_list3)
        status_rollups = self.obs_util.get_status_roll_ups(
            'ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'PD_1', RT.PlatformDevice)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'Sub_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)

        status_rollups = self.obs_util.get_status_roll_ups(
            'Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'Obs_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'Sub_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'PD_1')
        self._assert_status(status_rollups,
                            'IS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'ID_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)

    def test_get_status_roll_ups_platform_warn(self):
        self.mu.load_mock_resources(self.res_list)
        self.mu.load_mock_associations(self.assoc_list + self.assoc_list1 +
                                       self.assoc_list2)
        self.mu.load_mock_events(self.event_list4)

        self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

        # PD_1 power+comms warning
        status_rollups = self.obs_util.get_status_roll_ups(
            'ID_1', RT.InstrumentDevice)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'PD_1', RT.PlatformDevice)
        #log.warn("status %s" % status_rollups)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'IS_1', RT.InstrumentSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'PS_1', RT.PlatformSite)
        self.assertEquals(len(status_rollups), 6)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups('Sub_1', RT.Subsite)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'Sub_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

        status_rollups = self.obs_util.get_status_roll_ups(
            'Obs_1', RT.Observatory)
        self.assertIn('Obs_1', status_rollups)
        self.assertIn('Sub_1', status_rollups)
        self.assertIn('PS_1', status_rollups)
        self.assertIn('PD_1', status_rollups)
        self.assertIn('IS_1', status_rollups)
        self.assertIn('ID_1', status_rollups)
        self._assert_status(status_rollups,
                            'Obs_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'Sub_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PS_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups,
                            'PD_1',
                            agg=StatusType.STATUS_WARNING,
                            power=StatusType.STATUS_WARNING,
                            comms=StatusType.STATUS_WARNING)
        self._assert_status(status_rollups, 'IS_1')
        self._assert_status(status_rollups, 'ID_1')

    def _assert_status(self,
                       status_rollups,
                       res_id=None,
                       agg=StatusType.STATUS_OK,
                       loc=StatusType.STATUS_OK,
                       data=StatusType.STATUS_OK,
                       comms=StatusType.STATUS_OK,
                       power=StatusType.STATUS_OK):
        res_status = status_rollups[res_id] if res_id else status_rollups
        self.assertEquals(len(res_status), 5)
        self.assertEquals(res_status['agg'], agg)
        self.assertEquals(res_status['loc'], loc)
        self.assertEquals(res_status['data'], data)
        self.assertEquals(res_status['comms'], comms)
        self.assertEquals(res_status['power'], power)