Mongo replica set reconfig when primary and majority don't exist - c#

Is there anyway to reconfigure a replica set in the event the primary as well as a majority of the servers are down. For example if data center 1 goes does, a procedure can be run to reconfigure and set a new primary with the remaining servers?
I keep getting this "Command '$eval' failed: not master (response: { "note" : "from execCommand", "ok" : 0.0, "errmsg" : "not master" })"
We only have 2 data centers. (If we had 3 then I realize that would solve this problem.)
I was thinking about running a reconfigure on a 5 member replica set every time the fail over happens and changing the host of the arbiter from one data center to another so that the active data center will always have the arbiter, but I can't do that if 3 of the 5 members of the replica set aren't available...because not new primary will ever be set.
As a side note, I'm trying to do this in a .NET web service using the MongoDatabase.Eval() method of the mongo .NET driver, but even when I pass in a simple javascript method, I get an exception saying it failed because it's not the master. Is there another method I can use besides eval that doesn't require it to be executed on primary?
I'm fairly new mongo so if you have any suggestions, I'm all ears!

You can use rs.reconfig on the server.
http://docs.mongodb.org/manual/reference/method/rs.reconfig/
If majority of the servers are down then you will have to specify force option during reconfig.
rs.reconfig(cfg,{force:true});
Where cfg is you new configuration which has your currently live host.
Note: this has to be executed from mongo shell.

Related

LDAP - What to use instead of DirSyncRequestControl

I'm migrating some code away from Active Directory re-writing all directory requests to reference classes in System.Directory.Protocols and be LDAP v3 compliant. This is supposed to be a low level v3 LDAP namespace so assumed it wouldn't be polluted with AD specific types. The following code is from a monitor background worker that was already using the System.Directory.Protocols namespace. It opens an async long running request to AD and listens for changes using the Control DirSyncRequestControl.
SearchRequest request = new SearchRequest(
mDNSearchRoot,
mLdapFilter,
SearchScope.Subtree,
mAttrsToWatch
);
request.Controls.Add(
new DirSyncRequestControl(
mCookie,
mDirSyncOptions
)
);
mConn.BeginSendRequest(
request,
mRequestTimeout,
PartialResultProcessing.NoPartialResultSupport,
endPollDirectory,
null
);
It sends a cookie as a byte[] that tells the directory when to start querying from which is handy in case the background worker crashes and needs a restart later. In the endPollDirectory callback an update cookie is received and persisted immediately to the filesystem in the event of a restart being needed we always know when we last received results from. That cookie is loaded on restart and passed back with the DirSyncRequestControl.
The issue I'm facing is that DirSyncRequestControl is operating against an OID which specifically is an Active Directory extension, not standard LDAP. Our corporate directory is on IBM based LDAP and can't have AD OIDs and Controls applied. Standard LDAP supports "Persistent Search" 2.16.840.1.113730.3.4.3 but .NET doesn't provide a Control that could be added as in the above code. There's also no way to pass arguments like a cookie. The idea with the Persistent Search control is that you open the connection and as time passes the LDAP server sends changes back which I could response to. But on initiating the connection there's no way to specify when to returns results from, only results since the request was started will be received. If the monitor were to die and a directory change happened before the monitor could restart those changes could be neve be handled.
Does anyone know if there's an existing Control compliant with standard LDAP that could be added to the request which operates the way the AD specific DirSyncRequestControl does where a start date time could be passed?
Does anyone know if there's an existing Control compliant with standard LDAP that could be added to the request which operates the way the AD specific DirSyncRequestControl does where a start date time could be passed?
Standard would be the 1.3.6.1.4.1.4203.1.9.1.1 "Sync Request" control from RFC 4533, which is the basis of "Syncrepl" directory replication in OpenLDAP and 389-ds.
(Though "standard" does not guarantee that IBM's LDAP server will support it – or that it's enabled on your server specifically, similar to how OpenLDAP requires loading the "syncprov" overlay first.)
2.2. Sync Request Control
The Sync Request Control is an LDAP Control [RFC4511] where the
controlType is the object identifier 1.3.6.1.4.1.4203.1.9.1.1 and the
controlValue, an OCTET STRING, contains a BER-encoded
syncRequestValue. The criticality field is either TRUE or FALSE.
syncRequestValue ::= SEQUENCE {
mode ENUMERATED {
-- 0 unused
refreshOnly (1),
-- 2 reserved
refreshAndPersist (3)
},
cookie syncCookie OPTIONAL,
reloadHint BOOLEAN DEFAULT FALSE
}
The Sync Request Control is only applicable to the SearchRequest
Message.
Although dotnet doesn't support this control natively (it seems to focus on just supporting Active Directory extensions), it should be possible to create a custom class similar to the Dir­Sync­Request­Control class with the correct OID and correct BER serialization (and somehow handle the "Sync Done" control that delivers the final sync cookie to you, etc).
OpenLDAP's ldapsearch supports calling this control via ldapsearch -E sync=rp[/cookie]. On the server side, slapd supports this control for databases that have the "syncprov" overlay loaded (which is required for replication).
389-ds (Red Hat Directory Server) supports this control if the plug-in is enabled.
The other approach is to have a persistent search for (modifyTimestamp>=...) and keep track of the last received entry change timestamp in place of the "cookie". This isn't very accurate, unfortunately.

MongoClient ignores the connection string

I just started to use MongoDB(4.4) and its C# driver. I set up my MongoDB with the default option, localhost:27017. Then I turned on the authorization, created a superuser with root permission, like this:
db.createUser(
{
user: "superuser",
pwd: "123",
roles: [ "root" ]
}
)
I tested it on both Mongo shell and Compass, it all worked as expected, connected with correct password, and denied with the wrong one.
Then I created a C# windows form app, use NuGet to install all required packages such as MongoDB.Driver for C#(v2.11.0) and its related packages such as MongoDB.Bson, etc
After that, I used the following code to create a MongoClient:
MongoClient client = new MongoClient( "mongodb://superuser:12#localhost:27017" );
So I expected it should throw an exception because I used the wrong password, "12" in this case. But it didn't. Then I tried to list database names with:
client.ListDatabaseNames();
It threw a timeout exception: "A timeout occured after 30000ms selecting a server using CompositeServerSelector"
Even I used the correct password or turned off the authorization, and just go with "mongodb://localhost:27017" or ""mongodb://127.0.0.1:27017", it still threw the same timeout exception.
It feels like something wrong with that client it created which caused the timeout issue later on. But I couldn't figure out what I am missing.
Thank you for your help!
Edit:
The same code works perfectly in a console app, just not a windows form app, which really confuses me.
After trial and error for 2 days, I finally found a work around for this issue, still don't know why this works though.
So basically I have to split the MongoClient creation and its following function calls separately. I can't do anything related to the MongoClient right after its creation. For example, the following throws the time out exception:
MongoClient client = new MongoClient( "mongodb://localhost:27017" ); //I turned off authorization
client.ListDatabaseNames(); //Throw time out exception here!!!
I have to split them separately in 2 functions call, like one in a "Connect" button event, another one in a "ListDatabaseNames" button event.
Once I did that, everything works fine.
mongodb://superuser:12#localhost:27017?authMechanism=SCRAM-SHA-1
because dotNet not support SCRAM-SHA-256 yet
Creating a client does not perform any network operations like connecting to your MongoDB deployment - that is done in background. Hence incorrect credentials won't make client creation fail.
mongo shell works differently and compass probably performs some queries that would fail if credentials aren't correct.
Why you are getting a timeout error - my guess is it's an ipv4/ipv6 difference. Try 127.0.0.1 instead of localhost. If this doesn't help enable debug information in your driver.

App Insights Undefined Entries

I am using app insights in my web forms application and I get always entries with undefined description equal to the entities with named descritions.
Here is a snapshot: http://imgur.com/a/Coz8H
Always I get entries like this:
Why is the undefined tag count equal to the Windows 10 tag (almost always)?
What does the undefined tag mean, does it mean that the app insights has failed to recognize the operating system?
Is it because the undefined things are from the server side because I see many dependency calls to DATABASE and only POST requests when I further explore the tag's row.
Thanks.
Yes means Application Insights failed to recognize the operating system. THe reason it is equal to Windows10 tag looks purely coincidental.

How do I modify Entity Framework 6 using Npgsql 3 to use an SSL connected string?

So far what I've tried is to verify that my certificates for SSL are correct and through command line (Using psql) and through a console application (Npgsql) I'm able to reach the database with SSL enabled (No password needed). This is working.. My problem starts with the SSL.
The application I'm working on has working Data Access to Postgre using Entity Framework 6 on non-SSL. However when I try to update the string to use SSL, I need to find a place to pass in the client-certificates. I've looked at different places. Right now, I have changed the DbContext() constructor to use base(DbConnection,bool) so that I can pass in a connection that has been provided the callback method. However, I get this error:
The context cannot be used while the model is being created. This
exception may be thrown if the context is used inside the
OnModelCreating method or if the same context instance is accessed by
multiple threads concurrently. Note that instance members of DbContext
and related classes are not guaranteed to be thread safe.
I've tried to apply different fixes from SO to solve this error, but to no avail.
Anything helps!

MongoDB and C# driver socket timeouts in replica set with only one member

I have a C# web app running which connects with c# driver 1.7.0.4714 to a MongoDB. I want to put this one MongoDB into a replica set with two secondaries. When I restart my original MongoDB in replica set mode it gets the primary but then most of the connections from my web app fail with
System.Net.Sockets.SocketException
When I restart the MongoDB in non replica set mode everything works nicely again.
Here's my connection string: "mongodb://myserver:27017"
When you connect to a replica set, normally the driver can figure out that it's connecting to a replica set or a stand-alone server.
You don't say which version of the C# driver you are using, and you don't provide exact format of connection string/syntax you are using, but the tutorial covers this in detail here: http://www.mongodb.org/display/DOCS/CSharp+Driver+Tutorial#CSharpDriverTutorial-MongoClientclass.
It indicates that if only one server is specified and you don't specify replica set name, then direct mode is used, which is not what you want.
You should be using either replica set mode explicitly rather than default automatic mode, or you should specify the replica set name.
I found the answer which was quite easy, sorry to ask a dump question here:
I had my replcia set set up using domain names, i.e.
rs.add("myserver01")
rs.add("myserver02")
rs.add("myserver03")
The domain names myserver01, ..., could not be resolved on my application server and I connected using IP addresses: mongodb://10.0.0.1:27017,10.0.0.2:27017,10.0.0.3:27017
So every 2nd or third request failed. Fixing the connection string to use domain names and also fixing that the domain names could be resolved fixed everything.

Categories