示例#1
0
 private void updateTrackedResources(ApplicationId appId, boolean track) {
   if (intentService == null) {
     log.warn("Intent service is not bound yet");
     return;
   }
   intentService
       .getIntents()
       .forEach(
           intent -> {
             if (intent.appId().equals(appId)) {
               Key key = intent.key();
               Collection<NetworkResource> resources = Lists.newArrayList();
               intentService
                   .getInstallableIntents(key)
                   .stream()
                   .map(installable -> installable.resources())
                   .forEach(resources::addAll);
               if (track) {
                 addTrackedResources(key, resources);
               } else {
                 removeTrackedResources(key, resources);
               }
             }
           });
 }
示例#2
0
  private void removeIntent(IntentService intentService, Intent intent) {
    IntentListener listener = null;
    Key key = intent.key();
    final CountDownLatch withdrawLatch, purgeLatch;
    if (purgeAfterRemove || sync) {
      // set up latch and listener to track uninstall progress
      withdrawLatch = new CountDownLatch(1);
      purgeLatch = purgeAfterRemove ? new CountDownLatch(1) : null;
      listener =
          (IntentEvent event) -> {
            if (Objects.equals(event.subject().key(), key)) {
              if (event.type() == IntentEvent.Type.WITHDRAWN
                  || event.type() == IntentEvent.Type.FAILED) {
                withdrawLatch.countDown();
              } else if (purgeAfterRemove && event.type() == IntentEvent.Type.PURGED) {
                purgeLatch.countDown();
              }
            }
          };
      intentService.addListener(listener);
    } else {
      purgeLatch = null;
      withdrawLatch = null;
    }

    // request the withdraw
    intentService.withdraw(intent);

    if (purgeAfterRemove || sync) {
      try { // wait for withdraw event
        withdrawLatch.await(5, TimeUnit.SECONDS);
      } catch (InterruptedException e) {
        print("Timed out waiting for intent {} withdraw", key);
      }
      // double check the state
      IntentState state = intentService.getIntentState(key);
      if (purgeAfterRemove && (state == WITHDRAWN || state == FAILED)) {
        intentService.purge(intent);
      }
      if (sync) { // wait for purge event
        /* TODO
           Technically, the event comes before map.remove() is called.
           If we depend on sync and purge working together, we will
           need to address this.
        */
        try {
          purgeLatch.await(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
          print("Timed out waiting for intent {} purge", key);
        }
      }
    }

    if (listener != null) {
      // clean up the listener
      intentService.removeListener(listener);
    }
  }
示例#3
0
 @Deactivate
 public void deactivate() {
   store.unsetDelegate(delegate);
   eventDispatcher.removeSink(VirtualNetworkEvent.class);
   intentService.removeListener(intentListener);
   log.info("Stopped");
 }
示例#4
0
 @Activate
 public void activate() {
   store.setDelegate(delegate);
   eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
   intentService.addListener(intentListener);
   log.info("Started");
 }
示例#5
0
  /**
   * Checks both that the number of intents in submitted in the intent framework it's equal to the
   * number of intents expected and that all intents are equivalent.
   *
   * @param intents the list of intents expected
   */
  private void checkIntents(List<Intent> intents) {
    assertEquals(intents.size(), intentService.getIntentCount());

    for (Intent intentOne : intents) {
      boolean found = false;
      for (Intent intentTwo : intentService.getIntents()) {
        if (intentOne.key().equals(intentTwo.key())) {
          found = true;
          assertTrue(
              format("Comparing %s and %s", intentOne, intentTwo),
              IntentUtils.intentsAreEqual(intentOne, intentTwo));
          break;
        }
      }
      assertTrue(found);
    }
  }
示例#6
0
 /**
  * Creates an intent from a POST of a JSON string and attempts to apply it.
  *
  * @param stream input JSON
  * @return status of the request - CREATED if the JSON is correct, BAD_REQUEST if the JSON is
  *     invalid
  */
 @POST
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 public Response createIntent(InputStream stream) {
   try {
     IntentService service = get(IntentService.class);
     ObjectNode root = (ObjectNode) mapper().readTree(stream);
     Intent intent = codec(Intent.class).decode(root, this);
     service.submit(intent);
     UriBuilder locationBuilder =
         uriInfo
             .getBaseUriBuilder()
             .path("intents")
             .path(Short.toString(intent.appId().id()))
             .path(Long.toString(intent.id().fingerprint()));
     return Response.created(locationBuilder.build()).build();
   } catch (IOException ioe) {
     throw new IllegalArgumentException(ioe);
   }
 }
示例#7
0
  @Override
  protected void execute() {
    IntentService intentService = get(IntentService.class);
    CoreService coreService = get(CoreService.class);

    ApplicationId appId = appId();
    if (!isNullOrEmpty(applicationIdString)) {
      appId = coreService.getAppId(applicationIdString);
      if (appId == null) {
        print("Cannot find application Id %s", applicationIdString);
        return;
      }
    }

    if (isNullOrEmpty(keyString)) {
      for (Intent intent : intentService.getIntents()) {
        if (intent.appId().equals(appId)) {
          removeIntent(intentService, intent);
        }
      }

    } else {
      final Key key;
      if (keyString.startsWith("0x")) {
        // The intent uses a LongKey
        keyString = keyString.replaceFirst("0x", "");
        key = Key.of(new BigInteger(keyString, 16).longValue(), appId);
      } else {
        // The intent uses a StringKey
        key = Key.of(keyString, appId);
      }

      Intent intent = intentService.getIntent(key);
      if (intent != null) {
        removeIntent(intentService, intent);
      }
    }
  }
示例#8
0
  /**
   * Uninstalls a single intent by Id.
   *
   * @param appId the Application ID
   * @param keyString the Intent key value to look up
   */
  @DELETE
  @Path("{appId}/{key}")
  public void deleteIntentById(
      @PathParam("appId") String appId, @PathParam("key") String keyString) {
    final ApplicationId app = get(CoreService.class).getAppId(appId);

    Intent intent = get(IntentService.class).getIntent(Key.of(keyString, app));
    IntentService service = get(IntentService.class);

    if (intent == null) {
      intent = service.getIntent(Key.of(Long.decode(keyString), app));
    }
    if (intent == null) {
      // No such intent.  REST standards recommend a positive status code
      // in this case.
      return;
    }

    Key key = intent.key();

    // set up latch and listener to track uninstall progress
    CountDownLatch latch = new CountDownLatch(1);

    IntentListener listener = new DeleteListener(key, latch);
    service.addListener(listener);

    try {
      // request the withdraw
      service.withdraw(intent);

      try {
        latch.await(WITHDRAW_EVENT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
      } catch (InterruptedException e) {
        log.info("REST Delete operation timed out waiting for intent {}", key);
      }
      // double check the state
      IntentState state = service.getIntentState(key);
      if (state == WITHDRAWN || state == FAILED) {
        service.purge(intent);
      }

    } finally {
      // clean up the listener
      service.removeListener(listener);
    }
  }
示例#9
0
 protected void doIntentUpdate() {
   updateScheduled.set(false);
   if (intentService == null) {
     log.warn("Intent service is not bound yet");
     return;
   }
   try {
     // FIXME very inefficient
     for (IntentData intentData : intentService.getIntentData()) {
       try {
         trackIntent(intentData);
       } catch (NullPointerException npe) {
         log.warn("intent error {}", intentData.key(), npe);
       }
     }
   } catch (Exception e) {
     log.warn("Exception caught during update task", e);
   }
 }
示例#10
0
  @Override
  public void trackIntent(IntentData intentData) {

    // NOTE: This will be called for intents that are being added to the store
    //      locally (i.e. every intent update)

    Key key = intentData.key();
    Intent intent = intentData.intent();
    boolean isLocal = intentService.isLocal(key);
    boolean isInstalled = intentData.state() == INSTALLING || intentData.state() == INSTALLED;
    List<Intent> installables = intentData.installables();

    if (log.isTraceEnabled()) {
      log.trace(
          "intent {}, old: {}, new: {}, installableCount: {}, resourceCount: {}",
          key,
          intentsByDevice.values().contains(key),
          isLocal && isInstalled,
          installables.size(),
          intent.resources().size()
              + installables.stream().mapToLong(i -> i.resources().size()).sum());
    }

    if (isNullOrEmpty(installables) && intentData.state() == INSTALLED) {
      log.warn("Intent {} is INSTALLED with no installables", key);
    }

    // FIXME Intents will be added 3 times (once directly using addTracked,
    //       then when installing and when installed)
    if (isLocal && isInstalled) {
      addTrackedResources(key, intent.resources());
      for (Intent installable : installables) {
        addTrackedResources(key, installable.resources());
      }
      // FIXME check all resources against current topo service(s); recompile if necessary
    } else {
      removeTrackedResources(key, intent.resources());
      for (Intent installable : installables) {
        removeTrackedResources(key, installable.resources());
      }
    }
  }
示例#11
0
 @Override
 public void withdraw(Intent intent) {
   intentService.withdraw(intent);
 }
示例#12
0
 @Override
 public void submit(Intent intent) {
   intentService.submit(intent);
 }