On 05/11/10 07:23 AM, Darren Kenny wrote:
Hi Jean / Dave,

Comments inline...

On 05/10/10 06:21 PM, jean.mccormack wrote:
During the last prototype meeting, Dave and I were tasked with figuring
out the DOC interface to pass data to the checkpoint modules. We met to
discuss this last week with Evan and Sanjay attending for portions of
the meeting to help.
Input on this proposal is requested from Dermot, Darren, Karen and Sarah
but anyone else is welcome to respond.


There will be a class CheckpointNode that will be an ABC and will
inherit from DataObject. It will have a name attribute.
Each type of checkpoint (TI, TD, Transfer etc) will have it's own
subclass of CheckpointNode that will have attributes
    specific to that type of checkpoint.

The xml that will be generated would look like this:


<checkpoint>
<name>"name of checkpoint"</name>
<checkpoint specific attributes to be defined by each checkpoint>
</checkpoint>
Just curious why you are using a tag to specify the name as opposed to an
attribute - I feel that using an attribute is more capable of validation in
DTD, etc. but maybe I'm wrong, so I would think:

<checkpoint<name="name of checkpoint">
   <checkpoint specific attributes to be defined by each checkpoint>
</checkpoint>

OK. Done.


To further explain this I'll use an example of a client that does TD,
TI, TI, Transfer, Transfer. Note this is not meant
to be any real code, it's more  pseudocode than anything.

Client()

      td_node = TD_ChkptNode("TargetDiscovery")
      ti_node1 = TI_ChkptNode("TI_IPS")
      ti_node2 = TI_ChkptNode("TI_CPIO")
      xfer_node1 = Xfer_ChkptNode("XFER_IPS")
      xfer_node2 = Xfer_ChkptNode("XFER_CPIO")
      ...


      TD = register_checkpoint(td.discover, td_node)
      TI1 = register_checkpoint(ti.instantiate, ti_node1)
      TI2 = register_checkpoint(ti.instantiate, ti_node2)
      Xfer1 = register_checkpoint(xfer.transfer, xfer_node1)
      Xfer2 = register_checkpoint(xfer.transfer, xfer_node2)


      # Because we bounce out of engine after TD runs we may want to tell TD
where to put things.
      td_node.dst = "Discovered Targets" # TD_ChkptNode has property "dst"
which is just a name.
                                         # this name is the name it will give
the root node of
                                         # a tree of nodes, Physical and
Logical that it discoveres.

There are a couple of things that I see here:

- In the above code you seem to be using the same checkpoint, but with
   different parameters (TI and Transfer specifically) to do different things.
   This doesn't really fit with the Object-Oriented Design approach, where you
   would expect to have a class hierarchy like:


                                 TI
                               /    \
                        TI_IPS       TI_CPIO ...

    In other words there is a base-TI class, where all common functionality is,
    and then each specialization of this class for specific purposes - using
    this the above code would be more like:

        TD = register_checkpoint(td.discover)
        TI1 = register_checkpoint(ti_ips.instantiate)
        TI2 = register_checkpoint(ti_cpio.instantiate)
        Xfer1 = register_checkpoint(xfer_ips.transfer)
        Xfer2 = register_checkpoint(xfer_cpio.transfer)

        # Actually I'm not 100% sure what the .instantiate and .transfer
        # methods are meant to be... I would really have expected the
        # parameters to register_checkpoint to be simply class objects, e.g.
        #    TD = register_checkpoint(TargetData)
        #    TI1 = register_checkpoint(TargetInstantiationIps)
        #    TI2 = register_checkpoint(TargetInstantiationCpio)
        # ...


I think we'll stick with what was used in the prototype, which means it would be more like:

TD = register_checkpoint("target discovery", td.discover, TargetDiscovery) # name, path, func TI1 = register_checkpoint("instantiate ips", ti.instantiate, <func name to instantiate TI ips object>) TI2 = register_checkpoint("instantiate cpio area", ti.instantiate, <name to instantiate TI cpio object>)
Xfer 1 = register_checkpoint("Xfer IPS", transfer.transfer, create_transfer)
Xfer2 = register_checkpoint("Xfer CPIO", transfer.transfer, create_transfer)

I'll use transfer to explain what goes on here. During register_checkpoint for Xfer 1, create_transfer is executed. This function will grab the cache and look at the checkpoint node for "Xfer IPS" (get_child_by_name call into doc) which is created prior to this call. This node will have the type of transfer as an attribute. create_transfer will read that value and instantiate, in this case, a transfer IPS object and return it. So Xfer1 is a transfer IPS object.

- Each checkpoint should have a defined "interface" in that it would define
   what it takes in (via the DOC) and what it outputs (via the DOC).
Yes. That is part of each spec.
   As such, I would have thought that setting td_node.dst would be unnecessary
   since it would be the default for TD.
Only if there is a default. Again, that is an interface to be defined but there
might be a case to make it programmable. That belongs in the checkpoint
specific design. Let's just say that somehow the app knows where that data
is, either because it's in the default location or because it told TD where to put it.
   In the case of TD, it would have no input parameters, but would, by default,
   output a tree of discovered targets into the DOC. This would be a part of
   the "well-known and documented" interface.
Again, maybe on the input parameters. TBD.
      td_node.start = "..." # maybe for DC we don't want it to do physical
target discovery...
      # Now execute engine just running TD:
      execute(TD)

      # And now we need to add information to other nodes
      ti_node1.create = ... # root node of some tree of nodes that the App wants
      ti_node2.create = ... # root node of some tree of nodes that the App wants
      xfer_node1.src ="http://some/ips/repo:port";
      xfer_node1.dst = "rpool/jean/pkg_imag" # image area for  IPS to install 
to.
      xfer_node2.src = "/"
      xfer_node2.dst = "rpool/jean/whatever"   # area to cpio to
I'm really wary of objects being used like this - for example, if at anypoint
the application does a roll-back to a previous snapshot, in-process, then the
objects in the DOC will be different to the objects being used above.

As such, the use-case for anything stored in the DOC should be along the lines
of:

     ti_node1 = doc.get_child_by_name( "TI_IPS" );
     if ti_node1:
         ti_node1.create = ...
     else:
         # handle no entry, by either creating one, and inserting it or raising
         # an exception if it should be there.

If you don't do this, then there is a real chance of things not working as
expected.

And we could even wrap this into something like a method add_data_to_cache()?

Better?

Jean


      # And execute remaining checkpoints:
      execute(TI1, TI2, Xfer1, Xfer2) #<---- execute the rest of the 
checkpoints.
Thanks,

Darren.

_______________________________________________
caiman-discuss mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/caiman-discuss

Reply via email to