opendaylight: Genius install flow in switch - openflow

I am using opendaylight / Carbon and am trying to work with the Genius wrapper. I want to install a flow in a switch based on a MAC address match for an incoming packet. The instruction I want to install is a "GOTO" instruction. I proceed as follows:
FlowEntityBuilder flowEntityBuilder = new FlowEntityBuilder();
flowEntityBuilder.setTableId(tableId)
.setDpnId(dpnId)
.setFlowId(FlowUtils.createFlowId().toString())
.setFlowName("gotoTable1");
MatchInfo matchInfo = new MatchEthernetSource(macAddress);
InstructionInfo instructionInfo = new InstructionGotoTable(tableId);
FlowEntity flowEntity = flowEntityBuilder.addInstructionInfoList(instructionInfo).addMatchInfoList(matchInfo).build();
mdsalApiManager.installFlow(dpnId,flowEntity);
Mu intention was to create a flow entity and install it using the IMDSalApiManager.installFlow method.
Here is the exception that I see:
java.lang.IllegalArgumentException: Node (urn:opendaylight:flow:inventory?revision=2013-08-19)ethernet-source is missing mandatory descendant /(urn:opendaylight:flow:inventory?revision=2013-08-19)address
Any help debugging this would be appreciated.

This is how you build a GOTO instruction with OpenDaylight :
GoToTableBuilder gttb = new GoToTableBuilder();
gttb.setTableId(tableGoto);
Instruction gotoInstruction = new InstructionBuilder()
.setOrder(1).setInstruction(new GoToTableCaseBuilder()
.setGoToTable(gttb.build())
.build())
.build();
You can use this to adjust your code.

It turned out to be an issue on my end where the MacAddress supplied was null. I fixed this problem. However I still do not see the flow in the switch.

Related

Create a repository on a remote server with RDF4J

I've been trying to create a new repository on a remote GraphDB server using RDF4J, but I'm having problems.
This runs, but is seemingly not correct
HTTPRepositoryConfig implConfig = new HTTPRepositoryConfig(address);
RepositoryConfig repoConfig = new RepositoryConfig("test", "test", implConfig);
Model m = new
However, based on the info I get from "edit repository" in the workbench, the result doesn't look right. All the values are empty, except for id and title.
This fails
I tried to copy the settings from an existing repository that I created on the workbench, but that failed with:
org.eclipse.rdf4j.repository.config.RepositoryConfigException:
Unsupported repository type: owlim:MonitorRepository
The code for that attempt is inspired by the one found here . Except that the config file is based on an existing repo, as explained above. I also tried to config file provided in the example, but that failed aswell:
org.eclipse.rdf4j.repository.config.RepositoryConfigException:
Unsupported Sail type: graphdb:FreeSail
Anyone got any tips?
UPDATE
As Henriette Harmse correctly pointed out, I should have provided my code, not simply linked to it. That way I might have discovered that I hadn't done a complete copy after all, but changed the important first bits that she points out in her answer. Full code below:
String address = "serveradr";
RemoteRepositoryManager repositoryManager = new RemoteRepositoryManager( address);
repositoryManager.initialize();
// Instantiate a repository graph model
TreeModel graph = new TreeModel();
InputStream config = Rdf4jHelper.class.getResourceAsStream("/repoconf2.ttl");
RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE);
rdfParser.setRDFHandler(new StatementCollector(graph));
rdfParser.parse(config, RepositoryConfigSchema.NAMESPACE);
config.close();
// Retrieve the repository node as a resource
Resource repositoryNode = graph.filter(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY).subjects().iterator().next();
// Create a repository configuration object and add it to the repositoryManager
RepositoryConfig repositoryConfig = RepositoryConfig.create(graph, repositoryNode);
It fails on the last line.
ANSWERED #HenrietteHarmse gives the correct method in her answer below. The error is caused by missing dependencies. Instead of using RDF4J directly, I should have used the graphdb-free-runtime.
There are a number of issues here:
(1) RepositoryManager repositoryManager = new LocalRepositoryManager(new File(".")); will create a repository where ever your Java application is running from.
(2) Changing to new LocalRepositoryManager(new File("$GraphDBInstall/data/repositories")) will cause the repository to be created under the control of GraphDB (assuming you have a local GraphDB instance) only if GraphDB is not running. If you start GraphDB after running your program, you will be able to see the repository in GraphDB workbench.
(3) What you need to do is get the repository manager of the remote GraphDB, which can be done with RepositoryManager repositoryManager = RepositoryProvider.getRepositoryManager("http://IPAddressOfGraphDB:7200");.
(4) In the way you have specified the config, you cause the RDF graph config to be lost. The correct way to specify it is:
RepositoryConfig repositoryConfig = RepositoryConfig.create(graph, repositoryNode);
repositoryManager.addRepositoryConfig(repositoryConfig);
(5) A minor issue is that GraphUtil.getUniqueSubject(...) has been deprecated, for which you can use something like the following:
Model model = graph.filter(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY);
Iterator<Statement> iterator = model.iterator();
if (!iterator.hasNext())
throw new RuntimeException("Oops, no <http://www.openrdf.org/config/repository#> subject found!");
Statement statement = iterator.next();
Resource repositoryNode = statement.getSubject();
EDIT on 20180408:
(5) Or you can use the compact option as #JeenBroekstra suggested in the comments:
Models.subject(
graph.filter(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY))
.orElseThrow(() -> new RuntimeException("Oops, no <http://www.openrdf.org/config/repository#> subject found!"));
EDIT on 20180409:
For convenience I have added the complete code example here.
EDIT on 20180410:
So the actual culprit turned out to be an incorrect pom.xml. The correct version is as below:
<dependency>
<groupId>com.ontotext.graphdb</groupId>
<artifactId>graphdb-free-runtime</artifactId>
<version>8.4.1</version>
</dependency>
I believe I just had the same issue. I used the example code from GraphDB Free for running with RDF4J as a remote service and ran into the same exception as you (Unsupported Sail type: graphdb:FreeSail). Henriette Harmse's answer does not directly address this issue but one should follow the suggestions given there to avoid running into issues later. In addition, based on a look into the RDF4J code you need the following dependency in your pom.xml file (assuming GraphDB 8.5):
<dependency>
<groupId>com.ontotext.graphdb</groupId>
<artifactId>graphdb-free-runtime</artifactId>
<version>8.5.0</version>
</dependency>
This seems to be because there is some kind of service loading going on with META-INF, which I frankly am not familiar with. Maybe someone can provide more details in the comments. The requirement for adding this dependency in also seems to be absent from the instructions, so if this works for you, please let me know. Others who followed the same steps we did should be able to resolve this issue as well then.

Adding rules dynamically into drools engine

I have a standalone java application which will interact with my web application running on node. I am trying to add new rules dynamically through web UI. So far I am unable to figure it out, how to create and add rules. Any suggestions for the right direction would be helpful
This is basically a duplicate of https://stackoverflow.com/questions/25036973 so the following is basically a duplicate of my answer to that question...
It's probably best to just look at the Drools examples source code. For instance the KieFileSystem example shows how to create a rule from a String and launch a session which includes it.
The essentials are that you create a KieServices, which contains a virtual file system. You then add rules to that file system. A little bit like the following:
KieServices ks = KieServices.Factory.get();
KieRepository kr = ks.getRepository();
KieFileSystem kfs = ks.newKieFileSystem();
kfs.write("src/main/resources/my/rules/therule.drl", "The source code of the rule");
KieBuilder kb = ks.newKieBuilder(kfs);
kb.buildAll();
you can add multiple Compiled rule DRL files like
knowledgebuilder.add(new ByteArrayResource(compiledDRL.getBytes()),ResourceType.DRL);
Get all the knowledgePackages and fire the all rules
knowledgeBase kbase = knowledgeBaseFactory.newKnowledgeBase();
kbase.addknowledgePackages(knowledgeBuilder.getKnowledgePackages());
knowledgeSession ksession = kbase.newStatefullKnowledgeSession();
ksession.insert(inputObject);
ksession.fireAllRules();
ksession.dispose();

Application name is not set. Call Builder#setApplicationName. error

Application: Connecting to BigQuery using BigQuery APIs for Java
Environment: Eclipse, Windows 7
My application was running fine until last night. I've made no changes (except for restarting my computer) and my code is suddenly giving me this error:
Application name is not set. Call Builder#setApplicationName.
Thankfully I had a tar'd version of my workspace from last night. I ran a folder compare and found the local_db.bin file was different. I deleted the existing local_db.bin file and tried to run the program again. And it worked fine!
Any idea why this might have happened?
Hopefully this will help anyone else who stumbles upon this issue.
Try this to set your application name
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential)
.setApplicationName("Your app name")
.build();
If you are working with only Firebase Dynamic Links without Android or iOS app
Try this.
builder.setApplicationName(firebaseUtil.getApplicationName());
FirebaseUtil is custom class add keys and application name to this class
FirebaseDynamicLinks.Builder builder = new FirebaseDynamicLinks.Builder(
GoogleNetHttpTransport.newTrustedTransport(), JacksonFactory.getDefaultInstance(), null);
// initialize with api key
FirebaseDynamicLinksRequestInitializer firebaseDynamicLinksRequestInitializer = new FirebaseDynamicLinksRequestInitializer(
firebaseUtil.getFirebaseApiKey());
builder.setFirebaseDynamicLinksRequestInitializer(firebaseDynamicLinksRequestInitializer);
builder.setApplicationName(firebaseUtil.getApplicationName());
// build dynamic links
FirebaseDynamicLinks firebasedynamiclinks = builder.build();
// create Firebase Dynamic Links request
CreateShortDynamicLinkRequest createShortLinkRequest = new CreateShortDynamicLinkRequest();
createShortLinkRequest.setLongDynamicLink(firebaseUtil.getFirebaseUrlPrefix() + "?link=" + urlToShorten);
Suffix suffix = new Suffix();
suffix.setOption(firebaseUtil.getShortSuffixOption());
createShortLinkRequest.setSuffix(suffix);
// request short url
FirebaseDynamicLinks.ShortLinks.Create request = firebasedynamiclinks.shortLinks()
.create(createShortLinkRequest);
CreateShortDynamicLinkResponse createShortDynamicLinkResponse = request.execute();

this command is not available unless the connection is created with admin-commands enabled

When trying to run the following in Redis using booksleeve.
using (var conn = new RedisConnection(server, port, -1, password))
{
var result = conn.Server.FlushDb(0);
result.Wait();
}
I get an error saying:
This command is not available unless the connection is created with
admin-commands enabled"
I am not sure how do i execute commands as admin? Do I need to create an a/c in db with admin access and login with that?
Updated answer for StackExchange.Redis:
var conn = ConnectionMultiplexer.Connect("localhost,allowAdmin=true");
Note also that the object created here should be created once per application and shared as a global singleton, per Marc:
Because the ConnectionMultiplexer does a lot, it is designed to be
shared and reused between callers. You should not create a
ConnectionMultiplexer per operation. It is fully thread-safe and ready
for this usage.
Basically, the dangerous commands that you don't need in routine operations, but which can cause lots of problems if used inappropriately (i.e. the equivalent of drop database in tsql, since your example is FlushDb) are protected by a "yes, I meant to do that..." flag:
using (var conn = new RedisConnection(server, port, -1, password,
allowAdmin: true)) <==== here
I will improve the error message to make this very clear and explicit.
You can also set this in C# when you're creating your multiplexer - set AllowAdmin = true
private ConnectionMultiplexer GetConnectionMultiplexer()
{
var options = ConfigurationOptions.Parse("localhost:6379");
options.ConnectRetry = 5;
options.AllowAdmin = true;
return ConnectionMultiplexer.Connect(options);
}
For those who like me faced the error:
StackExchange.Redis.RedisCommandException: This operation is not
available unless admin mode is enabled: ROLE
after upgrading StackExchange.Redis to version 2.2.4 with Sentinel connection: it's a known bug, the workaround was either to downgrade the client back or to add allowAdmin=true to the connection string and wait for the fix.
Starting from 2.2.50 public release the issue is fixed.

Sharepoint Feature Upgrades

I have the following in my feature.template.xml
...
<VersionRange BeginVersion="1.0.0.1" EndVersion="1.0.0.2">
<CustomUpgradeAction Name="1.0.0.1_TO_1.0.0.2"></CustomUpgradeAction>
</VersionRange>
<VersionRange BeginVersion="1.0.0.2" EndVersion="1.0.0.3">
<CustomUpgradeAction Name="1.0.0.2_TO_1.0.0.3"></CustomUpgradeAction>
</VersionRange>
...
My feature upgrade event is as follows:
public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
{
using (SPSite site = (SPSite)properties.Feature.Parent)
using (SPWeb mySite = site.RootWeb)
{
switch (upgradeActionName)
{
case "1.0.0.1_TO_1.0.0.2":
//execute logicA
break;
case "1.0.0.2_TO_1.0.0.3":
//execute logicB
break;
default:
break;
}
}
Am I correct in saying that if the site is currently version 1.0.0.0, it will be upgraded to v 1.0.03, executing both logicA and logicB above. This means that sharepoint would call featureupgrading event for each version upgrade.Is this correct? Or do I need to do something different to achieve this?
I also have the following concerns:
What exactly do the the BeginVersion and EndVersion mean.
I especially do not understand the BeginVersion. What happens if instead of 1.0.0.2 I set it to 1.0.0.1 as well?
Any assistance would be greately appreciated, as I did not find any good relevant details online or on books.
When you add a new Feature to your VS SharePoint project, Visual studio initializes your Feature with version 0.0.0.0.
In the properties window you can set a version number for your feature.
When you want to upgrade an existing feature you'll have to define the range of versions for which you want your upgrade actions (code, new manifest, ...) to happen.
E.g.: You deployed your feature without changing the version number. Your current deployed feature has version number 0.0.0.0.
You want to upgrade your feature and set the version number to 2.0.0.0.
If you define a versionrange as follows:
<VersionRange BeginVersion="1.0.0.0" EndVersion="2.0.0.0">
You'll notice nothing will happen when you call SPFeature.Upgrade() since 0.0.0.0 is not in the defined versionrange.
If you use this versionrange
<VersionRange EndVersion="2.0.0.0">
or
<VersionRange BeginVersion="0.0.0.0" EndVersion="2.0.0.0">
You'll notice your FeatureUpgrading eventreceiver or other upgrade actions will be triggered.
Your upgraded feature will now have version number 2.0.0.0.
If you call SPFeature.Upgrade again nothing will happen again, because 2.0.0.0 exceeds the defined versionrange. So BeginVersion is included, EndVersion not.
Every feature with a version number between [0.0.0.0 - 1.x.x.x] will be upgraded if you use the latter versionranges.
I think you can also leave the BeginVersion and EndVersion attributes entirely out. Then you're upgradeactions will be triggered at every SPFeature.Upgrade() call. (To be verified)
For more information: Chris O'Brien wrote an interesting articles series about this topic, cfr. http://www.sharepointnutsandbolts.com/2010/06/feature-upgrade-part-1-fundamentals.html