Can I open a clustered MQ queue for writing in Perl? - perl

If I have a Websphere MQ queue defined on another queue manager in the cluster, is there a way I can open it for writing using the Perl interface? The code below brings back mqrc 2085.
$messageQ = MQSeries::Queue->new
(
QueueManager => $qMgr,
Queue => $queue,
Options => $openOpt
) or die ">>>ERROR2: Unable to open the queue: $queue\n";
}

Yes! The Perl modules are a thin veneer over the WMQ API and expose all the basic options and most of the really esoteric stuff as well.
When you open a queue, WebSphere MQ performs name resolution on the values you provide for Queue and QMgr names. If you provide both a Queue and a QMgr name then the object reference is fully qualified and WMQ will attempt to open it as named. So if the name you provide is the local QMgr and the clustered queue does not have a locally defined instance, the open will fail with a 2085 Unknown Object Name.
The trick to opening a clustered queue is to provide a null value for the QMgr name. This causes name resolution to check the local QMgr for a queue of the same name, then finding none it checks the cluster repository and resolve the open to the clustered queue. Note that the queue must be advertised to the cluster for this to work. Specifically, the CLUSTER or CLUSNL attribute of the target queue must be non-blank and refer to a cluster that the source QMgr participates in. Similarly, the destination QMgr must also participate in the same cluster as the source QMgr.
Note also that if you specify a QMgr name on the open that is not the local QMgr, then WMQ will attempt to resolve the QMgr name only. If it can resolve a route to that QMgr then it will send the message there. This means that in a cluster you can send a message to any queue on any QMgr so long as you know the fully-qualified name.
Finally, you can define a local alias over a clustered queue. For example if you are on QMGRA and DEF QA(TARGET.QUEUE) TARGQ(TARGET.QUEUE) and then on QMGRB and QMGRC in the same cluster you DEF QL(TARGET.QUEUE) CLUSTER(MYCLUS) then it is possible to open QMGR=QMGRA QUEUE=TARGET.QUEUE and still have it work as expected. Note that the alias is NOT advertised to the cluster but the target queue is. The only issue with this approach is that the first time it is opened the API call may fail if the cluster query takes too long. When I do this in Production, I always use amqsput on the alias ahead of time to make the QMgr query the repository before the actual application opens the queue. Why would you do this? If security is a concern you probably don't want to authorize all apps directly to the cluster XMitQ because, as noted above, they could then put a message onto any queue on any QMgr in the cluster, including SYSTEM.ADMIN.COMMAND.QUEUE. The alias gives you a place to hang authorizations and restrict the user to specific destinations in the cluster.
So short answer, make sure you provide a null QMgr name on the Open call or set up a local alias over the clustered queue. For more about the security aspects of this, see the WMQ Security presentation at http://t-rob.net/links

Related

Specify postgresql database name in cloud foundry manifest.yml

Is there a way to specify a postgresql database name to connect to in the cloud foundry manifest.yml file? I've been raking through the documentation and haven't yet found this specific information.
I'm imagining something like this:
applications:
- name: my-app
routes:
- route: my-app.mybluemix.net
services:
- postgres
dbname: database2
With that approach, a postgresql connection can be made by just the connection string provided by VCAP_SERVICES parsing modules (cfenv in the case of node).
If this is not possible, I will just set a dbname environment variable and build my own connection string.
There is nothing like that in a Cloud Foundry application manifest.yml.
The manifest.yml only takes a list of service instance names and the services with those names will be bound to your app. It does not allow you set other metadata.
https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#services-block
I don't know if these will help, but when you cf bind-service directly there are two additional provisions you can make use of (these are not supported by manifest.yml as of me writing this):
Arbitrary bind parameters. These probably won't help unless your service broker supports them, but it's a way to pass additional info to the service broker. If your broker supported it, you could in theory say give me a database named XYZ by passing it some config this way.
Named service bindings. This provides what amounts to a second name. The intent is that you can create the service with a name of X, but your application can look for a service binding with name Y. You can use this to swap in differently named services, but still expose the same binding name to the application so it will always find the service.
If you are trying to pass in some other service instance related metadata to your application, you'd need to do it some other way. Like if you want to tell it the database name or the connection pool size, etc.. Using environment variables like you mentioned is one option. You could use a config file or cli arguments passed to your application. What you pick is probably a matter of preference/support in the library/framework you're using.
For what it's worth, most service brokers I've seen pass in and tell you a specific database name to use. If the broker said connect to db XYZ and you made your connection to myCoolDb, the connection would fail. Just wanted to mention this. Your mileage may vary.

MessageQueue.Exists(QueueName) returns false but it exists

The problem I'm having is with this code:
if (!MessageQueue.Exists(QueueName))
{
MessageQueue.Create(QueueName, true);
}
It will check if a queue exists; if it doesn't I want it to create the queue. This code has been working and hasn't changed for a few months. Today I started receiving this error:
[MessageQueueException (0x80004005): A queue with the same path name
already exists.] System.Messaging.MessageQueue.Create(String path,
Boolean transactional) +239478
The queues are local and if I delete the specific queue it will work once. After the queue is created it starts to fail again with the same error message.
It looks like the issue may be because of the Network Load Balancing (NLB) configuration. I was unaware of a change that recently put the machine in a NLB environment. The configuration we are using is an unsupported one.
More information is in How Message Queuing can function over Network Load Balancing (NLB).

How to make ActiveMQ transportConnector property environmentaly-dependent

I'm looking for a way to replace this on my ActiveMQ config:
<transportConnector uri="tcp://localhost:60019"> disableAsyncDispatch="false"/>
with a "not-hardcoded" URI (e.g., replacing "localhost" with a variable that resolves to an instance dependent value). The problem is that as we have many JBoss instances per server, and that URI above resolves to 0.0.0.0:60019, only one instance at a time can be running, unless we configure it in a per-application basis, which is not only frustrating, but there are circumstances where it is not enough (should be per-instance based, which is much more frustrating).
Each JBoss server has its own IP address, so I thought of using ${jboss.bind.address} to circumvent this, but it won't syntax. We also have an environment variable %SERVERIP% which could be used for this calling it from a start up script, but I don't know if ActiveMQ reads an environment variable for assigning its transport connector URI.
Any help would be much appreciated.
Use a PropertyPlaceHolderConfigurer and you should be able to replace the uri with some ${variable} from file or from jvm system variable. This should work since ActiveMQ configuration is really just a Spring context.

Activation pending in CQ5

I have created a test page in the Geometrixx site in CQ5. I can see the page very well on 4502 port (author environment). But when I activate the page to see it on the 4503 port (Publish environment) , I always see the yellow colored icon in front of the page on console which on hover says 'Activation pending. #1 in Queue'
Is there some workflow attached to it ? If so, how can I check it out and probably kill it (for now) ? Or is there some other reason ?
The default replication queue settings points to localhost:4503. If your publish instance is not located on the same machine as the author instance (which is common), you will need to change the settings to point to a valid publish instance. Once a valid publish instance is configured the items queued for activation should get processed and the icons will change from yellow to green.
If the queue is blocked, you can clear it by:
going to /etc/replication/agents.author.html
Clicking on the default replication agent.
Then clicking on 'clear' above the queue. This will clear the entire
queue.
If you want to clear one or more specific items in the queue, you can select
them then click clear.
This page has a few steps on troubleshooting replication agents:
http://helpx.adobe.com/cq/kb/replication-stuck.html
This page has some general information about replication agents:
http://dev.day.com/docs/en/cq/current/deploying/configuring_cq.html#Replicating from Author to Publish
You can inspect the replication queues at
http://localhost:4502/etc/replication.html
The default agent is
http://localhost:4502/etc/replication/agents.author/publish.html
From here you can test the connection, view the log, and see what's in the queue. You can also clear the queue or force retry.
there is a way to see a "final View" of your test page without to publish: wcmmode=disabled
http:// localhost: 4502/cf#/content/geometrixx/folder/test.html
Just delete /cf# and add ?wcmmode=disabled after the extension.
http:// localhost: 4502/content/geometrixx/folder/test.html?wcmmode=disabled
One thing not explicitly mentioned so far: You need TWO instances of AEM running. Ports 4502 and 4503 don't point to different modes of the same instance, as AEM only listens to the one port (in general). So you will need to copy your Author jar to a new directory and name it something like cq5-publish-4503.jar
In addition, you may need to update your maven pom files for code deploys. You CAN set installed bundles on author to auto replicate/publish however.

Query on DNS & connect to existing vm

In my current code base, when i create a VM, DNS name is being dynamically set as same as the instance name. For example, consider if my VM name is "anandInstance", DNS name of the name is being generated as "anandInstance.cloudapp.net". Is there a way to change the DNS name like "dns1.cloudapp.net" during the creation thru REST API??
"Connect to existing VM" , is it possible to achieve this option through REST call? In case "connect to existing.." option , we are getting a list of vms/services to choose and VM is getting created successfully. How to achieve the same using API.
Thanks
In my current code base, when i create a VM, DNS name is being
dynamically set as same as the instance name. For example, consider if
my VM name is "anandInstance", DNS name of the name is being generated
as "anandInstance.cloudapp.net". Is there a way to change the DNS name
like "dns1.cloudapp.net" during the creation thru REST API??
I don't think it is possible. Imagine what a nightmare in the portal would become if you were able to do so? How would you link a Cloud Service (whatever.cloudapp.net) to an actual deployment (MyDemoVm123). However you can use your own domain and have CNAME records pointing to your "want-to-change-for-some-reason.cloudapp.net" (frankly I surely think that soon we will use even longer names)
"Connect to existing VM" , is it possible to achieve this option
through REST call?
Connection to a VM is essentially opening a RDP session. If it a windows VM, you can try using the Download RDP file API call. Once you get the file, just start it with "process.start". If it is linux VM, just start SSH client on port 22 (or one you have defined) from the Cloud Service DNS name you have.
UPDATE
From the azure portal,for stand alone machineoption, we are able to give the dns name with deafult cloudoneapp.net. How to do the same
through the rest api call.any specfic paramter is there to specify the
same?
When you are using the REST API, you first create a Cloud Service (still named hosted service in the REST API) where your machine will be hosted. Here you give the name for that hosted service (the dns name with deafult cloudoneapp.net). Then you call the Create Virtual Machine Deployment API action.
In case "connect to existing.." option , we are getting a list of vms/services to choose and VM is getting created successfully. How to
achieve the same using API.
When you want to get list of all VMs, just get a list of all Hosted Services, then get properties of each and make a guess whether it is a VM or a Cloud Service (maybe by querying for Properties of each service). I don't see a direct access to the list of Virtual Machines. But as this feature being PREVIEW, things might change in the future.
Hope my answer is clear?