[wildfly-dev] profile cloning tool

Brian Stansberry brian.stansberry at redhat.com
Wed Sep 24 08:59:20 EDT 2014


Following is a discussion that started being about low level details on 
how to implement a particular feature and has instead morphed into a 
broader design discussion. So it seemed better to have it on the dev 
list. Dev list readers, sorry for the jump into the middle of something 
with no background.

Heiko,

The only connection to you is about the record/replay format, yes. Not 
just the format in a general sense though, but also architecturally 
where/how the conversion to that format is done. Which depends on what 
the format is and how it's used.

The fundamental format is the native DMR format. If the only use cases 
the console has involve storing stuff for its own use, without user 
involvement, then you guys could stick with that.

Once end users start dealing with recording and replay, we already have 
a format, in the form of CLI scripts, and a replay device, the CLI. 
These scripts are very commonly used. So for sure we are going to get 
requests to record stuff in CLI script form, at least from CLI users.

If the console use cases also involve recording in the CLI format, then 
I think we should aim for a common code base for converting to/from that 
format. Maintain all the quoting and escaping stuff in one place. Deal 
with quirks there. For example, the CLI uses the 'batch' commands to 
encapsulate steps into a composite op. CLI users don't have to deal with 
the complex nesting involved in a raw DMR composite op.

If that code is all maintained in one place, then the question is how 
does the console use it? Compile it in? Ask the server to do conversion 
for it? My mention of a generic op was about the latter.

On 9/24/14, 2:15 AM, Heiko Braun wrote:
>
>
> Apologies, I didn't really follow this thread. But one question comes to my mind:
>
> We always had requests for record/replay functionality. This ultimately boils down to the question what format the recorded operation should use. It seems to be related to questions Brian raised.  Isn't that central data format part of both the profile cloning and the record/replay features? Do these two share anything else?
>
>
> My 2 cents.
>
> On 23 Sep 2014, at 21:16, Brian Stansberry <brian.stansberry at redhat.com> wrote:
>
>> I see. That's not the WFLY-1106 task though. WFLY-1106 is meant to be a live clone. Sorry if that wasn't clear.
>>
>> I've added Alexey and Heiko Braun in cc.
>>
>> I'm not comfortable with having the server directly create CLI scripts. Particularly writing a file. I think that belongs on the client side.
>>
>> Brainstorming a bit now...
>>
>> I also don't like returning CLI syntax as the response for anything but a single totally generic op. Not for something custom purpose like cloning. Over time we'd end up with a bunch of those kind of custom things, each added for some special purpose.
>>
>> I can, however, see a totally generic op being useful. We have, for example, console RFEs for outputing CLI scripts to correspond to what the console has done. Having a generic op the console could invoke to get back the necessary string *might* make sense.
>>
>> A facility like that could then be used by the CLI itself as part of a client-side solution to this kind of thing.
>>
>> Possibly whether to perform the live update could be a param to the clone op. Either way the return value of the op is the list of needed operations; the param simply controls whether the server applies them.
>>
>> If the live update isn't performed, the client can instead turn around and ask the server to translate the return value into CLI syntax.
>>
>> It would make more sense for the CLI to do that translation itself though. But the DMR->CLI logic it uses could be reused by the server for the generic op I mentioned.
>>
>> On 9/23/14, 7:19 AM, Tom Fonteyne wrote:
>>> all customer are asking how to turn a profile into a CLI script. None
>>> that I know are actually interested in a "live" clone.
>>>
>>> I started with a standalone client:
>>> https://github.com/tfonteyn/profilecloner
>>>
>>>
>>> On 23/09/14 13:11, Emanuel Muckenhuber wrote:
>>>> Hi,
>>>>
>>>> i am not so sure whether writing those operations to a file and
>>>> converting them to the CLI format makes much sense as part of the mgmt
>>>> API in general. We don't have this concept anywhere in the mgmt API at
>>>> the moment and only the CLI really understands (implements) the way
>>>> commands are parsed on the client side.
>>>>
>>>> In particular i am concerned about having those workarounds for
>>>> generating CLI scripts as part of the mgmt API contracts. This really
>>>> should be a client side thing (if required), but i don't really know
>>>> what the failures you were running into are.
>>>>
>>>> The ProfileCloneLiveHandler looks correct and having nested classes
>>>> there seems to be totally fine. Speaking of composite operations, we
>>>> should make sure to also test a composite operations cloning a profile
>>>> and reading it as a 2nd step. I suspect this will cause some problems
>>>> with the ordering of some handlers.
>>>>
>>>> I hope this helps and thanks,
>>>> Emanuel
>>>>
>>>> On 23/09/14 10:04, Tom Fonteyne wrote:
>>>>>
>>>>> On 22/09/14 17:37, Brian Stansberry wrote:
>>>>>> On 9/22/14, 10:44 AM, Tom Fonteyne wrote:
>>>>>>> well... if it was not for some bugs in wildfly ... it would all work
>>>>>>> now :)
>>>>>>>
>>>>>>> 1. PathAddress.pathAddress(node.require(OP_ADDR)).toCLIStyleString()
>>>>>>> -> toCLIStyleString does not quote the value part
>>>>>>> --> temp workaround, but I'll log a JIRA and do a pull-request
>>>>>>>
>>>>>>
>>>>>> OK, but how is this relevant to this work?
>>>>> writing the profile to a CLI file. For example without quoting:
>>>>>
>>>>> /profile=default/subsystem=undertow/server=default-server/host=default-host/location=/:add(handler="welcome-content")
>>>>>
>>>>>
>>>>> => breaks as the value "/" is seen as an address separator.
>>>>> Its no big deal as I just build the string myself for now.
>>>>>
>>>>> https://github.com/tfonteyn/wildfly-core/tree/WFLY-1106
>>>>>
>>>>>          modified:
>>>>> controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java
>>>>>
>>>>>
>>>>>          modified:
>>>>> controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java
>>>>>
>>>>>
>>>>>          modified:
>>>>> host-controller/src/main/java/org/jboss/as/domain/controller/operations/ProfileCloneHandler.java
>>>>>
>>>>>
>>>>>          modified:
>>>>> host-controller/src/main/java/org/jboss/as/domain/controller/resources/ProfileResourceDefinition.java
>>>>>
>>>>>
>>>>>          modified:
>>>>> host-controller/src/main/resources/org/jboss/as/domain/controller/resources/LocalDescriptions.properties
>>>>>
>>>>>
>>>>>
>>>>> ProfileCloneHandler.java
>>>>>
>>>>> Look at private ProfileCloneLiveHandler class.
>>>>>
>>>>> Note I used a single java file with two internal classes - I wasn't sure
>>>>> if there is a "contained" policy or if I should simply use 3 classes.
>>>>>
>>>>> All feedback is obviously very welcome.
>>>>>
>>>>> cheers
>>>>> Tom
>>>>>
>>>>>
>>>>>>
>>>>>>> 2. The describe information for the transaction subsystem used as-is
>>>>>>> does do the "add" but will in fact install broken xml
>>>>>>> -> will investigate, then log JIRA
>>>>>>>
>>>>>>> 3. The datasource describe can be added, but fails to marchal its
>>>>>>> config
>>>>>>> to xml due to issues with the "driver-name" child
>>>>>>>      -> will investigate, then log JIRA
>>>>>>>
>>>>>>> 4. JGroups subsystem is problematic due to it's use of the
>>>>>>> "add-protocol" command.In CLI you would do:
>>>>>>>
>>>>>>>     /profile="test"/subsystem="jgroups"/stack="udp":add()
>>>>>>> /profile="test"/subsystem="jgroups"/stack="udp":add-protocol(type="PING")
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>     but the ProfileAddHandler sees this as the same address (which it
>>>>>>> is) and tells me "Duplicate resource"
>>>>>>>     In my humble opinion we should change that to:
>>>>>>> /profile="test"/subsystem="jgroups"/stack="udp"/protocol=PING:add()
>>>>>>>
>>>>>>>    Keep add-protocol for backwards compatibility, but let
>>>>>>> "describe" use
>>>>>>> a normal "add"
>>>>>>>    -> will log JIRA
>>>>>>>
>>>>>>> Other then that (ahum) cloning to a new profile works.
>>>>>>
>>>>>> Do you have a link to what you're doing? Having all these issues with
>>>>>> "describe" sounds a bit odd. You wouldn't be able to boot a managed
>>>>>> domain server if describe doesn't work.
>>>>>>
>>>>>>> Cloning to a file fully works.
>>>>>>>
>>>>>>> Kind regards
>>>>>>> Tom
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 18/09/14 14:44, Emanuel Muckenhuber wrote:
>>>>>>>>
>>>>>>>> On 18/09/14 15:34, Tom Fonteyne wrote:
>>>>>>>>> ok - part one is done and functioning well
>>>>>>>>> I can now write the profile to a file as CLI commands
>>>>>>>>>
>>>>>>>>> second part is the live cloning option still todo.
>>>>>>>>>
>>>>>>>>> But I have a small issue left. The cloning to the file works
>>>>>>>>> fine, and
>>>>>>>>> yet despite setting
>>>>>>>>>
>>>>>>>>> context.getResult().set(SUCCESS);
>>>>>>>>
>>>>>>>> The outcome of the operation will be a success if the operation
>>>>>>>> completes. The context.getResult() is the response i.e. a simple
>>>>>>>> value
>>>>>>>> for metrics or a more complex structure for the read-resource
>>>>>>>> operation.
>>>>>>>>
>>>>>>>>> context.stepCompleted();
>>>>>>>>>
>>>>>>>>> the operation says:
>>>>>>>>>
>>>>>>>>> [domain at localhost:9990 /]
>>>>>>>>> /profile=full-ha:clone(file=/tmp/q2,profile-name=qq)
>>>>>>>>> {
>>>>>>>>>      "outcome" => "failed",
>>>>>>>>>      "result" => "success",
>>>>>>>>>      "failure-description" => "WFLYCTL0159: Operation handler
>>>>>>>>> failed to
>>>>>>>>> complete",
>>>>>>>>>      "rolled-back" => true
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> I presume that I need some sort of commit ? I did look at some other
>>>>>>>>> handlers of course but I seem to miss it.
>>>>>>>>>
>>>>>>>>
>>>>>>>> This just means there is a context.stepCompleted(); call missing for
>>>>>>>> one of the stepHandlers and therefore the operation gets rolled back.
>>>>>>>> This is easy to miss in particular for nested handlers.
>>>>>>>>
>>>>>>>> Emanuel
>>>>>>>>
>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 17/09/14 16:19, Emanuel Muckenhuber wrote:
>>>>>>>>>>
>>>>>>>>>> On 17/09/14 16:44, Tom Fonteyne wrote:
>>>>>>>>>>>
>>>>>>>>>>> I started on doing this but could use some doc's for those steps.
>>>>>>>>>>>
>>>>>>>>>>> I have so far:
>>>>>>>>>>> - added "clone" with attributes
>>>>>>>>>>> - registered the ProfileCloneHandler
>>>>>>>>>>> - ProfileCloneHandler sets up the describe opp.
>>>>>>>>>>> - must now execute it....
>>>>>>>>>>>
>>>>>>>>>>> public void execute(OperationContext context, ModelNode operation)
>>>>>>>>>>> throws OperationFailedException {
>>>>>>>>>>> <snip>
>>>>>>>>>>>          ModelNode profileDescription = new ModelNode();
>>>>>>>>>>>          ModelNode describeProfile = new ModelNode();
>>>>>>>>>>> describeProfile.get(OP).set(ModelDescriptionConstants.DESCRIBE);
>>>>>>>>>>> describeProfile.get(OP_ADDR).set(address.toModelNode());
>>>>>>>>>>>
>>>>>>>>>>> // is this correct ? will it execute the describe (and block while
>>>>>>>>>>> doing
>>>>>>>>>>> so)
>>>>>>>>>>>          context.addStep(profileDescription, describeProfile,
>>>>>>>>>>> ProfileDescribeHandler.INSTANCE, OperationContext.Stage.MODEL);
>>>>>>>>>>>
>>>>>>>>>>> // I presume I can now take profileDescription and create file
>>>>>>>>>>> and/or
>>>>>>>>>>> new profile...
>>>>>>>>>>>     doBla();
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> You would need to add another nested step to have access to the
>>>>>>>>>> result
>>>>>>>>>> of the describe operations. The context.addStep() is not
>>>>>>>>>> blocking and
>>>>>>>>>> just adds it to a queue of handlers which are executed after the
>>>>>>>>>> current one finishes.
>>>>>>>>>>
>>>>>>>>>> In this step you should be able to get the resolved operations
>>>>>>>>>> using
>>>>>>>>>> profileDescription.get("result").asList() and would then need to
>>>>>>>>>> get
>>>>>>>>>> the operation handlers from the mgmt resource registration and add
>>>>>>>>>> those as another step. So there are going to be a lot of nested
>>>>>>>>>> steps ;)
>>>>>>>>>>
>>>>>>>>>>> // is this the last step before leaving execute, or should this be
>>>>>>>>>>> done
>>>>>>>>>>> to actually kick of the describe .. and should doBla() be done
>>>>>>>>>>> *after*
>>>>>>>>>>> this ?
>>>>>>>>>>>
>>>>>>>>>>>          context.stepCompleted();
>>>>>>>>>>>
>>>>>>>>>>> any good doc on StepHandler and related would be gladly
>>>>>>>>>>> welcomed :)
>>>>>>>>>>>
>>>>>>>>>>> Kind regards
>>>>>>>>>>> Tom
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 16/09/14 16:23, Brian Stansberry wrote:
>>>>>>>>>>>> This time really bringing him into the loop.
>>>>>>>>>>>>
>>>>>>>>>>>> On 9/16/14, 10:10 AM, Brian Stansberry wrote:
>>>>>>>>>>>>> Bringing Emanuel Muckenhuber into the loop.
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 8/26/14, 9:32 AM, Brian Stansberry wrote:
>>>>>>>>>>>>>> On 8/26/14, 7:43 AM, Tom Fonteyne wrote:
>>>>>>>>>>>>>>> Hi Brian,
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I've been digging into the relevant source (what else does
>>>>>>>>>>>>>>> one do
>>>>>>>>>>>>>>> on a
>>>>>>>>>>>>>>> bank holiday Monday in the UK in the bleeping torrential
>>>>>>>>>>>>>>> rain...)
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I looked at:
>>>>>>>>>>>>>>> org.jboss.as.domain.controller.resources.ProfileResourceDefinition
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> to add the "clone" command
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Yep.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> (I do need to look at commands that take
>>>>>>>>>>>>>>> arguments as well)
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> org.jboss.as.controller.operations.global.WriteAttributeHandler
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I don't think this is relevant. You'd add a step that
>>>>>>>>>>>>>> invokes the
>>>>>>>>>>>>>> ProfileDescribeHandler and then take the output (a list of
>>>>>>>>>>>>>> ops) and
>>>>>>>>>>>>>> change the address of each op to the new profile name, and
>>>>>>>>>>>>>> then add
>>>>>>>>>>>>>> each
>>>>>>>>>>>>>> of those steps.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> org.jboss.as.domain.controller.operations.ProfileDescribeHandler
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> on how to do this stephandler
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I wanted to start getting the command "working" but without
>>>>>>>>>>>>>>> doing
>>>>>>>>>>>>>>> anything
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Idiot questions:
>>>>>>>>>>>>>>> - is the above the right way of tackling this ?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Yes.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>    I presume the correct place to add a handler is in
>>>>>>>>>>>>>>> "org.jboss.as.domain.controller.operations"
>>>>>>>>>>>>>>>    but that would mean clone is only on profile level (and
>>>>>>>>>>>>>>> not for
>>>>>>>>>>>>>>> example on datasource level)
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I think that's fine to start. If you get a clone of an entire
>>>>>>>>>>>>>> profile
>>>>>>>>>>>>>> clone working, you'll learn a lot, we'll have something useful,
>>>>>>>>>>>>>> and it
>>>>>>>>>>>>>> should be straightforward enough to further advance that
>>>>>>>>>>>>>> work to
>>>>>>>>>>>>>> make it
>>>>>>>>>>>>>> more generally useful.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>    -> hopefully I'm wrong, but would a clone need to be
>>>>>>>>>>>>>>> added to
>>>>>>>>>>>>>>> every
>>>>>>>>>>>>>>> single level ??
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> What I want to do later is add a 'copy' op to the root
>>>>>>>>>>>>>> resource,
>>>>>>>>>>>>>> which
>>>>>>>>>>>>>> will take a source and target address. It can use the existing
>>>>>>>>>>>>>> subsystem
>>>>>>>>>>>>>> level describe ops to get anything related to subsystems. That
>>>>>>>>>>>>>> would
>>>>>>>>>>>>>> get
>>>>>>>>>>>>>> more data than is needed if, say, cloning only a single
>>>>>>>>>>>>>> datasource
>>>>>>>>>>>>>> was
>>>>>>>>>>>>>> the goal, but that's ok. I don't want to add any further
>>>>>>>>>>>>>> requirement to
>>>>>>>>>>>>>> subsystem authors to support this, so we'll rely on the
>>>>>>>>>>>>>> existing
>>>>>>>>>>>>>> 'describe' op.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>         ... as a global operation would be out as "describe"
>>>>>>>>>>>>>>> does
>>>>>>>>>>>>>>> not
>>>>>>>>>>>>>>> exist other then on profile (and sub-profile)
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Yes, a 'describe'-like function for resources outside
>>>>>>>>>>>>>> subsystems
>>>>>>>>>>>>>> is a
>>>>>>>>>>>>>> prerequisite for doing more than the profile clone op. But we
>>>>>>>>>>>>>> can do
>>>>>>>>>>>>>> that within core, without adding any requirement on subsystem
>>>>>>>>>>>>>> authors. I
>>>>>>>>>>>>>> don't know exactly when we'll be able to provide that for you,
>>>>>>>>>>>>>> which is
>>>>>>>>>>>>>> one reason I think starting with just the full profile clone
>>>>>>>>>>>>>> makes
>>>>>>>>>>>>>> sense.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> - how do I make wildfly use my newly build wild-fly core ?
>>>>>>>>>>>>>>>    I tried updating the pom to the new core version, but it
>>>>>>>>>>>>>>> seems to
>>>>>>>>>>>>>>> refuse to use the local copy
>>>>>>>>>>>>>>>    Note; I'm *not* good at maven :/
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> You need the following in your command to maven:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> -Dversion.org.wildfly.core=1.0.0.Alpha6-SNAPSHOT
>>>>>>>>>>>>>> -Dskip-enforce=true
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> e.g.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> ./build.sh -Dversion.org.wildfly.core=1.0.0.Alpha6-SNAPSHOT
>>>>>>>>>>>>>> -Dskip-enforce=true
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The first one is a general thing you can do to change a version
>>>>>>>>>>>>>> from
>>>>>>>>>>>>>> what's defined in the pom. If you look in the root pom.xml,
>>>>>>>>>>>>>> there's a
>>>>>>>>>>>>>> long properties section where the version of everything is
>>>>>>>>>>>>>> defined. So
>>>>>>>>>>>>>> that -D just overrides one of those property values.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The -Dskip-enforce=true turns of a validation thing that bans
>>>>>>>>>>>>>> transitive
>>>>>>>>>>>>>> dependencies. That validation just causes trouble when you are
>>>>>>>>>>>>>> working
>>>>>>>>>>>>>> with snapshots.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> - do I make any sense ?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Yes.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> - is there any dev doc I can read on this subject ?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> This doc is really about adding subsystems, but it's the only
>>>>>>>>>>>>>> docs
>>>>>>>>>>>>>> about
>>>>>>>>>>>>>> writing handlers, etc:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> https://docs.jboss.org/author/display/WFLY9/Extending+WildFly
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The biggest thing is to really understand the OperationContext
>>>>>>>>>>>>>> interface, which is extensively javadoced.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> In particular, you need to understand the addStep methods,
>>>>>>>>>>>>>> since
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> essence of what you are doing is adding steps and passing data
>>>>>>>>>>>>>> back and
>>>>>>>>>>>>>> forth between their handlers.  A trick to understand is the
>>>>>>>>>>>>>> variant(s)
>>>>>>>>>>>>>> of addStep that let you pass in a 'response' ModelNode. For
>>>>>>>>>>>>>> example,
>>>>>>>>>>>>>> you
>>>>>>>>>>>>>> could
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 1) create a ModelNode.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 2) add a step that will trigger use of ProfileDescribeHandler,
>>>>>>>>>>>>>> passing
>>>>>>>>>>>>>> in the ModelNode from 1) as the response.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 3) Add a step that will take the 'describe' results from 2,
>>>>>>>>>>>>>> munge the
>>>>>>>>>>>>>> addresses, and then add steps to execute all those ops. This 3)
>>>>>>>>>>>>>> step
>>>>>>>>>>>>>> will have a ref to the ModelNode from 1), allowing it to see
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> result
>>>>>>>>>>>>>> of the work done by 2).
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> - I will be out on holiday next week, so take your take
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Enjoy!
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> cheers
>>>>>>>>>>>>>>> Tom
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On 18/08/14 16:45, Brian Stansberry wrote:
>>>>>>>>>>>>>>>> On 8/18/14, 10:30 AM, Tom Fonteyne wrote:
>>>>>>>>>>>>>>>>>> Do you have any interest in looking into that?
>>>>>>>>>>>>>>>>> sure - if I can I will :)
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> But you'll need to send me details on where to hook up in
>>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>>> code/modules
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Great. Just a warning -- this will be a fairly complex task.
>>>>>>>>>>>>>>>> But
>>>>>>>>>>>>>>>> hopefully not crazily so. :) And hopefully interesting.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Seems JIRA works, so long as you don't need to log in.
>>>>>>>>>>>>>>>> There are two JIRAs:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> https://issues.jboss.org/browse/WFLY-1106
>>>>>>>>>>>>>>>> https://issues.jboss.org/browse/WFLY-1706
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> The second is really more of a duplicate of the former and
>>>>>>>>>>>>>>>> I'll
>>>>>>>>>>>>>>>> probably close it as such.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> This would be part of WildFly Core (I'll move the issues to
>>>>>>>>>>>>>>>> WFCORE at
>>>>>>>>>>>>>>>> some point.)
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> What's needed is an implementation of the
>>>>>>>>>>>>>>>> OperationStepHandler
>>>>>>>>>>>>>>>> interface in the WildFly Core controller module. We can chat
>>>>>>>>>>>>>>>> off-list
>>>>>>>>>>>>>>>> about details.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Doing this for profiles (or children of standalone server
>>>>>>>>>>>>>>>> subsystems)
>>>>>>>>>>>>>>>> should be fairly straightforward, because the "describe"
>>>>>>>>>>>>>>>> operation
>>>>>>>>>>>>>>>> that I mentioned exists. Moving to other resources outside
>>>>>>>>>>>>>>>> of a
>>>>>>>>>>>>>>>> profile/subsystem will require some work from my team, to
>>>>>>>>>>>>>>>> provide
>>>>>>>>>>>>>>>> some
>>>>>>>>>>>>>>>> sort of analogue to the "describe" operation.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> To show you what I mean about the describe operation, here I
>>>>>>>>>>>>>>>> run it
>>>>>>>>>>>>>>>> from the CLI against a standalone server's datasource
>>>>>>>>>>>>>>>> subsystem.
>>>>>>>>>>>>>>>> The
>>>>>>>>>>>>>>>> result is a list, where each element in the list is the
>>>>>>>>>>>>>>>> equivalent of
>>>>>>>>>>>>>>>> a low level operation.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> [standalone at localhost:9990 /] /subsystem=datasources:describe
>>>>>>>>>>>>>>>> {
>>>>>>>>>>>>>>>>     "outcome" => "success",
>>>>>>>>>>>>>>>>     "result" => [
>>>>>>>>>>>>>>>>         {
>>>>>>>>>>>>>>>>             "operation" => "add",
>>>>>>>>>>>>>>>>             "address" => [("subsystem" => "datasources")]
>>>>>>>>>>>>>>>>         },
>>>>>>>>>>>>>>>>         {
>>>>>>>>>>>>>>>>             "deployment-name" => undefined,
>>>>>>>>>>>>>>>>             "driver-name" => "h2",
>>>>>>>>>>>>>>>>             "driver-module-name" => "com.h2database.h2",
>>>>>>>>>>>>>>>>             "module-slot" => undefined,
>>>>>>>>>>>>>>>>             "driver-class-name" => undefined,
>>>>>>>>>>>>>>>>             "driver-datasource-class-name" => undefined,
>>>>>>>>>>>>>>>> "driver-xa-datasource-class-name" =>
>>>>>>>>>>>>>>>> "org.h2.jdbcx.JdbcDataSource",
>>>>>>>>>>>>>>>>             "xa-datasource-class" => undefined,
>>>>>>>>>>>>>>>>             "driver-major-version" => undefined,
>>>>>>>>>>>>>>>>             "driver-minor-version" => undefined,
>>>>>>>>>>>>>>>>             "jdbc-compliant" => undefined,
>>>>>>>>>>>>>>>>             "operation" => "add",
>>>>>>>>>>>>>>>>             "address" => [
>>>>>>>>>>>>>>>>                 ("subsystem" => "datasources"),
>>>>>>>>>>>>>>>>                 ("jdbc-driver" => "h2")
>>>>>>>>>>>>>>>>             ]
>>>>>>>>>>>>>>>>         },
>>>>>>>>>>>>>>>>         {
>>>>>>>>>>>>>>>>             "connection-url" =>
>>>>>>>>>>>>>>>> "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE",
>>>>>>>>>>>>>>>>             "driver-class" => undefined,
>>>>>>>>>>>>>>>>             "datasource-class" => undefined,
>>>>>>>>>>>>>>>>             "jndi-name" =>
>>>>>>>>>>>>>>>> "java:jboss/datasources/ExampleDS",
>>>>>>>>>>>>>>>>             "driver-name" => "h2",
>>>>>>>>>>>>>>>>             "new-connection-sql" => undefined,
>>>>>>>>>>>>>>>>             "url-delimiter" => undefined,
>>>>>>>>>>>>>>>> "url-selector-strategy-class-name" => undefined,
>>>>>>>>>>>>>>>>             "use-java-context" => true,
>>>>>>>>>>>>>>>>             "jta" => undefined,
>>>>>>>>>>>>>>>>             "max-pool-size" => undefined,
>>>>>>>>>>>>>>>>             "min-pool-size" => undefined,
>>>>>>>>>>>>>>>>             "initial-pool-size" => undefined,
>>>>>>>>>>>>>>>>             "pool-prefill" => undefined,
>>>>>>>>>>>>>>>>             "pool-use-strict-min" => undefined,
>>>>>>>>>>>>>>>>             "capacity-incrementer-class" => undefined,
>>>>>>>>>>>>>>>>             "capacity-decrementer-class" => undefined,
>>>>>>>>>>>>>>>>             "user-name" => "sa",
>>>>>>>>>>>>>>>>             "password" => "sa",
>>>>>>>>>>>>>>>>             "security-domain" => undefined,
>>>>>>>>>>>>>>>>             "reauth-plugin-class-name" => undefined,
>>>>>>>>>>>>>>>>             "flush-strategy" => undefined,
>>>>>>>>>>>>>>>>             "allow-multiple-users" => undefined,
>>>>>>>>>>>>>>>>             "connection-listener-class" => undefined,
>>>>>>>>>>>>>>>>             "connection-properties" => undefined,
>>>>>>>>>>>>>>>> "prepared-statements-cache-size" => undefined,
>>>>>>>>>>>>>>>>             "share-prepared-statements" => undefined,
>>>>>>>>>>>>>>>>             "track-statements" => undefined,
>>>>>>>>>>>>>>>>             "allocation-retry" => undefined,
>>>>>>>>>>>>>>>>             "allocation-retry-wait-millis" => undefined,
>>>>>>>>>>>>>>>>             "blocking-timeout-wait-millis" => undefined,
>>>>>>>>>>>>>>>>             "idle-timeout-minutes" => undefined,
>>>>>>>>>>>>>>>>             "query-timeout" => undefined,
>>>>>>>>>>>>>>>>             "use-try-lock" => undefined,
>>>>>>>>>>>>>>>>             "set-tx-query-timeout" => undefined,
>>>>>>>>>>>>>>>>             "transaction-isolation" => undefined,
>>>>>>>>>>>>>>>>             "check-valid-connection-sql" => undefined,
>>>>>>>>>>>>>>>>             "exception-sorter-class-name" => undefined,
>>>>>>>>>>>>>>>> "stale-connection-checker-class-name" => undefined,
>>>>>>>>>>>>>>>> "valid-connection-checker-class-name" => undefined,
>>>>>>>>>>>>>>>>             "background-validation-millis" => undefined,
>>>>>>>>>>>>>>>>             "background-validation" => undefined,
>>>>>>>>>>>>>>>>             "use-fast-fail" => undefined,
>>>>>>>>>>>>>>>>             "validate-on-match" => undefined,
>>>>>>>>>>>>>>>>             "spy" => undefined,
>>>>>>>>>>>>>>>>             "use-ccm" => undefined,
>>>>>>>>>>>>>>>>             "enabled" => true,
>>>>>>>>>>>>>>>>             "connectable" => undefined,
>>>>>>>>>>>>>>>>             "statistics-enabled" => undefined,
>>>>>>>>>>>>>>>>             "tracking" => undefined,
>>>>>>>>>>>>>>>>             "reauth-plugin-properties" => undefined,
>>>>>>>>>>>>>>>>             "exception-sorter-properties" => undefined,
>>>>>>>>>>>>>>>> "stale-connection-checker-properties" => undefined,
>>>>>>>>>>>>>>>> "valid-connection-checker-properties" => undefined,
>>>>>>>>>>>>>>>>             "connection-listener-property" => undefined,
>>>>>>>>>>>>>>>> "capacity-incrementer-properties" => undefined,
>>>>>>>>>>>>>>>> "capacity-decrementer-properties" => undefined,
>>>>>>>>>>>>>>>>             "operation" => "add",
>>>>>>>>>>>>>>>>             "address" => [
>>>>>>>>>>>>>>>>                 ("subsystem" => "datasources"),
>>>>>>>>>>>>>>>>                 ("data-source" => "ExampleDS")
>>>>>>>>>>>>>>>>             ]
>>>>>>>>>>>>>>>>         },
>>>>>>>>>>>>>>>>         {
>>>>>>>>>>>>>>>>             "connection-url" =>
>>>>>>>>>>>>>>>> "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE",
>>>>>>>>>>>>>>>>             "driver-class" => undefined,
>>>>>>>>>>>>>>>>             "datasource-class" => undefined,
>>>>>>>>>>>>>>>>             "jndi-name" =>
>>>>>>>>>>>>>>>> "java:jboss/datasources/ExampleDS",
>>>>>>>>>>>>>>>>             "driver-name" => "h2",
>>>>>>>>>>>>>>>>             "new-connection-sql" => undefined,
>>>>>>>>>>>>>>>>             "url-delimiter" => undefined,
>>>>>>>>>>>>>>>> "url-selector-strategy-class-name" => undefined,
>>>>>>>>>>>>>>>>             "use-java-context" => true,
>>>>>>>>>>>>>>>>             "jta" => undefined,
>>>>>>>>>>>>>>>>             "max-pool-size" => undefined,
>>>>>>>>>>>>>>>>             "min-pool-size" => undefined,
>>>>>>>>>>>>>>>>             "initial-pool-size" => undefined,
>>>>>>>>>>>>>>>>             "pool-prefill" => undefined,
>>>>>>>>>>>>>>>>             "pool-use-strict-min" => undefined,
>>>>>>>>>>>>>>>>             "capacity-incrementer-class" => undefined,
>>>>>>>>>>>>>>>>             "capacity-decrementer-class" => undefined,
>>>>>>>>>>>>>>>>             "user-name" => "sa",
>>>>>>>>>>>>>>>>             "password" => "sa",
>>>>>>>>>>>>>>>>             "security-domain" => undefined,
>>>>>>>>>>>>>>>>             "reauth-plugin-class-name" => undefined,
>>>>>>>>>>>>>>>>             "flush-strategy" => undefined,
>>>>>>>>>>>>>>>>             "allow-multiple-users" => undefined,
>>>>>>>>>>>>>>>>             "connection-listener-class" => undefined,
>>>>>>>>>>>>>>>>             "connection-properties" => undefined,
>>>>>>>>>>>>>>>> "prepared-statements-cache-size" => undefined,
>>>>>>>>>>>>>>>>             "share-prepared-statements" => undefined,
>>>>>>>>>>>>>>>>             "track-statements" => undefined,
>>>>>>>>>>>>>>>>             "allocation-retry" => undefined,
>>>>>>>>>>>>>>>>             "allocation-retry-wait-millis" => undefined,
>>>>>>>>>>>>>>>>             "blocking-timeout-wait-millis" => undefined,
>>>>>>>>>>>>>>>>             "idle-timeout-minutes" => undefined,
>>>>>>>>>>>>>>>>             "query-timeout" => undefined,
>>>>>>>>>>>>>>>>             "use-try-lock" => undefined,
>>>>>>>>>>>>>>>>             "set-tx-query-timeout" => undefined,
>>>>>>>>>>>>>>>>             "transaction-isolation" => undefined,
>>>>>>>>>>>>>>>>             "check-valid-connection-sql" => undefined,
>>>>>>>>>>>>>>>>             "exception-sorter-class-name" => undefined,
>>>>>>>>>>>>>>>> "stale-connection-checker-class-name" => undefined,
>>>>>>>>>>>>>>>> "valid-connection-checker-class-name" => undefined,
>>>>>>>>>>>>>>>>             "background-validation-millis" => undefined,
>>>>>>>>>>>>>>>>             "background-validation" => undefined,
>>>>>>>>>>>>>>>>             "use-fast-fail" => undefined,
>>>>>>>>>>>>>>>>             "validate-on-match" => undefined,
>>>>>>>>>>>>>>>>             "spy" => undefined,
>>>>>>>>>>>>>>>>             "use-ccm" => undefined,
>>>>>>>>>>>>>>>>             "enabled" => true,
>>>>>>>>>>>>>>>>             "connectable" => undefined,
>>>>>>>>>>>>>>>>             "statistics-enabled" => undefined,
>>>>>>>>>>>>>>>>             "tracking" => undefined,
>>>>>>>>>>>>>>>>             "reauth-plugin-properties" => undefined,
>>>>>>>>>>>>>>>>             "exception-sorter-properties" => undefined,
>>>>>>>>>>>>>>>> "stale-connection-checker-properties" => undefined,
>>>>>>>>>>>>>>>> "valid-connection-checker-properties" => undefined,
>>>>>>>>>>>>>>>>             "connection-listener-property" => undefined,
>>>>>>>>>>>>>>>> "capacity-incrementer-properties" => undefined,
>>>>>>>>>>>>>>>> "capacity-decrementer-properties" => undefined,
>>>>>>>>>>>>>>>>             "operation" => "add",
>>>>>>>>>>>>>>>>             "address" => [
>>>>>>>>>>>>>>>>                 ("subsystem" => "datasources"),
>>>>>>>>>>>>>>>>                 ("data-source" => "ExampleDS")
>>>>>>>>>>>>>>>>             ]
>>>>>>>>>>>>>>>>         }
>>>>>>>>>>>>>>>>     ]
>>>>>>>>>>>>>>>> }
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> On 18/08/14 16:04, Brian Stansberry wrote:
>>>>>>>>>>>>>>>>>> Cool. That can be quite helpful. It's nice to see folks
>>>>>>>>>>>>>>>>>> writing
>>>>>>>>>>>>>>>>>> tooling based on the management API. :)
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> There's a JIRA out there for doing this on the server side
>>>>>>>>>>>>>>>>>> instead of
>>>>>>>>>>>>>>>>>> the client side. So a user invokes an op and the server
>>>>>>>>>>>>>>>>>> handles it.
>>>>>>>>>>>>>>>>>> For sure that will be done for EAP 7. Do you have any
>>>>>>>>>>>>>>>>>> interest in
>>>>>>>>>>>>>>>>>> looking into that?
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> The jboss.org site is down for maintenance, or I'd send
>>>>>>>>>>>>>>>>>> you the
>>>>>>>>>>>>>>>>>> link
>>>>>>>>>>>>>>>>>> to the JIRA.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> The server-side can utilize an internal operation called
>>>>>>>>>>>>>>>>>> "describe" to
>>>>>>>>>>>>>>>>>> get the exact ops needed to create a profile. From there
>>>>>>>>>>>>>>>>>> it's
>>>>>>>>>>>>>>>>>> just a
>>>>>>>>>>>>>>>>>> matter of changing the addresses to point to the target.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> On 8/18/14, 7:04 AM, Tom Fonteyne wrote:
>>>>>>>>>>>>>>>>>>> Hi,
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> I decided to stick my head into DMR code and as a result
>>>>>>>>>>>>>>>>>>> ended up
>>>>>>>>>>>>>>>>>>> writing a Profile Clone tool
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> It connects to a running domain controller, reads the
>>>>>>>>>>>>>>>>>>> desired
>>>>>>>>>>>>>>>>>>> origin
>>>>>>>>>>>>>>>>>>> profile and spits out a file with CLI commands.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> I't not limited to profiles, it can basically read any
>>>>>>>>>>>>>>>>>>> root
>>>>>>>>>>>>>>>>>>> element
>>>>>>>>>>>>>>>>>>> (not
>>>>>>>>>>>>>>>>>>> all make sense of course) so you can also for example
>>>>>>>>>>>>>>>>>>> clone
>>>>>>>>>>>>>>>>>>> socket-binding-group
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> I've tested it with full-ha with added datasources and
>>>>>>>>>>>>>>>>>>> security
>>>>>>>>>>>>>>>>>>> domains.
>>>>>>>>>>>>>>>>>>> Will it handle any profile ? Well, it should... but if you
>>>>>>>>>>>>>>>>>>> have
>>>>>>>>>>>>>>>>>>> one
>>>>>>>>>>>>>>>>>>> that
>>>>>>>>>>>>>>>>>>> breaks then please let me know.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> There is a caveat with hornetq conection factories though:
>>>>>>>>>>>>>>>>>>> double
>>>>>>>>>>>>>>>>>>> check
>>>>>>>>>>>>>>>>>>> if the right connector is set.
>>>>>>>>>>>>>>>>>>> Correct manually in the output if needed !
>>>>>>>>>>>>>>>>>>> Check the entries:
>>>>>>>>>>>>>>>>>>> /profile=.*/subsystem=messaging/hornetq-server=.*/connection-factory=.*
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> and see/correct the connector attribute:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>     connector={\"in-vm\" => undefined}
>>>>>>>>>>>>>>>>>>> or
>>>>>>>>>>>>>>>>>>>     connector={\"netty\" => undefined}
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> The reason is that the Cloner class does not set undefined
>>>>>>>>>>>>>>>>>>> values
>>>>>>>>>>>>>>>>>>> which
>>>>>>>>>>>>>>>>>>> is logical,
>>>>>>>>>>>>>>>>>>> but the hornetq connector must be defined with an
>>>>>>>>>>>>>>>>>>> "undefined"
>>>>>>>>>>>>>>>>>>> which is
>>>>>>>>>>>>>>>>>>> not logical...
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Get the binary from here:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> http://zen.usersys.redhat.com/downloads/eap/apps/profilecloner.jar
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> http://zen.usersys.redhat.com/downloads/eap/apps/profilecloner.sh
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> The sh file is bare-bones and expect JBOSS_HOME to be
>>>>>>>>>>>>>>>>>>> set. Or
>>>>>>>>>>>>>>>>>>> without
>>>>>>>>>>>>>>>>>>> the sh:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>   java -cp
>>>>>>>>>>>>>>>>>>> $JBOSS_HOME/bin/client/jboss-cli-client.jar:profilecloner.jar
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> org.jboss.tfonteyne.profilecloner.Main
>>>>>>>>>>>>>>>>>>>      --controller=<host> --username=<user>
>>>>>>>>>>>>>>>>>>> --password=<password>
>>>>>>>>>>>>>>>>>>> --port=<number> --file=<name>
>>>>>>>>>>>>>>>>>>>      rootelement from to [rootelement from to] ....
>>>>>>>>>>>>>>>>>>>    where "rootelement from to" is for example:
>>>>>>>>>>>>>>>>>>>        socket-binding-group full-ha-sockets
>>>>>>>>>>>>>>>>>>> full-ha-sockets-copy
>>>>>>>>>>>>>>>>>>>        profile full-ha full-ha-copy
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> example:
>>>>>>>>>>>>>>>>>>>   java -cp
>>>>>>>>>>>>>>>>>>> $JBOSS_HOME/bin/client/jboss-cli-client.jar:profilecloner.jar
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> org.jboss.tfonteyne.profilecloner.Main
>>>>>>>>>>>>>>>>>>> --controller=localhost
>>>>>>>>>>>>>>>>>>> --user=admin --password=secret --file=output.cli profile
>>>>>>>>>>>>>>>>>>> full-ha
>>>>>>>>>>>>>>>>>>> mycopy
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> The sources are here:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> https://github.com/tfonteyn/profilecloner
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Is the code any good ? Can engineering use it to stick it
>>>>>>>>>>>>>>>>>>> into the
>>>>>>>>>>>>>>>>>>> product ?
>>>>>>>>>>>>>>>>>>> I dunno... it works but was build with trial and error.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> PLEASE send me feedback !
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Kind regards
>>>>>>>>>>>>>>>>>>> Tom
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>
>>
>>
>> --
>> Brian Stansberry
>> Senior Principal Software Engineer
>> JBoss by Red Hat
>


-- 
Brian Stansberry
Senior Principal Software Engineer
JBoss by Red Hat


More information about the wildfly-dev mailing list