On 16-07-15 17:58, John Burwell wrote:
> Wido,
> 
> We have an acute problem — Oracle will be issuing no further security patches 
> for Java7 which is a significant opsec risk.  Put simply, we can’t leave our 
> users exposed to such a risk because Ubuntu won’t ship a release for an 
> non-EOL’ed Java version for another year.  Personally, I think it is a 
> tremendous oversight that Java7 has been EOL’ed for over three (3) months 
> [1], and we have not addressed the issue for our users.  CloudStack should 
> have officially supported Java8 before Java7 reached EOL.
> 

True, true. I'm not against going to Java 8, I just don't want to
abandon the Ubuntu users.

The PPA however is a good way to go, that could go into the Release
Notes and Upgrade docs.

> To minimize the impact of the change and smooth the transition, I suggest 
> continuing to build with source and runtime compatibility set to 1.7 and test 
> builds on both Java7 and Java8 until CloudStack 5.  This approach will allow 
> users to gradually transition from Java7 to Java8 with support for Java7 
> being eliminated at the next major release.
> 

Yes, that would be best. But don't we have a Java 8 Jenkins slave already?

Wido

> Thanks,
> -John
> 
> [1]: http://www.oracle.com/technetwork/java/eol-135779.html
> 
> ---
> John Burwell (@john_burwell)
> VP of Software Engineering, ShapeBlue
> (571) 403-2411 | +44 20 3603 0542
> http://www.shapeblue.com
> Please join us at CloudStack Collab EU — 
> http://events.linuxfoundation.org/events/cloudstack-collaboration-conference-europe
> 
> 
> 
> 
>> On Jul 15, 2015, at 7:57 AM, Wido den Hollander <w...@widodh.nl> wrote:
>>
>> Signed PGP part
>>
>>
>> On 15-07-15 09:20, Wilder Rodrigues wrote:
>>> If there would be dependencies on some other things, that in no way
>>> could be fixed now, we could wait for 4.7 (5.0). However, if we
>>> could give it a go, I would be able to tackle this in our next
>>> Sprint (within 1 1/2 week from now) and still get it into 4.6.
>>>
>>> What would be the main considerations?
>>>
>>
>> Well, on Ubuntu systems we simply we will require a additional
>> software repo. The good thing is that OpenJDK 8 is available for 12.04
>> and 14.04
>>
>> I don't feel like we should do something like this in a 4.X release,
>> but that's me.
>>
>> Wido
>>
>>> Cheers, Wilder
>>>
>>>
>>> On 14 Jul 2015, at 22:25, Wido den Hollander
>>> <w...@widodh.nl<mailto:w...@widodh.nl>> wrote:
>>>
>>>
>>>
>>> On 07/14/2015 10:18 PM, John Burwell wrote: Wido,
>>>
>>> Is the OpenJDK PPA [1] not acceptable?  Since Java7 is no longer
>>> supported, we run the risk of an Java security issue affecting the
>>> project that won’t be fixed.
>>>
>>>
>>> I didn't know that a PPA with OpenJDk existed. Looking at it I see
>>> that the maintainer Matthias Klose works for Canonical, so it
>>> seems like an official PPA.
>>>
>>> Still, having users adding PPAs is something we want to prevent as
>>> much as possible, but I do recognize the problem here.
>>>
>>> Ubuntu 16.04 is less then a year away and will have Java 8 support,
>>> so that will be resolved by then, but for now it is a problem.
>>>
>>> I think that CloudStack 4.6 is to early, but maybe 4.7 (called
>>> 5.0?) is a good time to make the move?
>>>
>>> Wido
>>>
>>> Thanks, -John
>>>
>>> [1]: https://launchpad.net/~openjdk-r/+archive/ubuntu/ppa
>>>
>>> --- John Burwell (@john_burwell) VP of Software Engineering,
>>> ShapeBlue (571) 403-2411 | +44 20 3603 0542
>>> http://www.shapeblue.com Please join us at CloudStack Collab EU —
>>> http://events.linuxfoundation.org/events/cloudstack-collaboration-conf
>>>
>>>
>> erence-europe
>>>
>>>
>>>
>>>
>>>
>>> On Jul 10, 2015, at 5:47 PM, Wido den Hollander
>>> <w...@widodh.nl<mailto:w...@widodh.nl>> wrote:
>>>
>>> Signed PGP part
>>>
>>>
>>> On 07/10/2015 09:22 PM, Rohit Yadav wrote: Ping Wilder - any
>>> progress/plan on moving forward (perhaps after 4.6?).
>>>
>>>
>>> I don't think there is? Since Ubuntu 14.04 doesn't support Java 8
>>> in any package form we can't really continue.
>>>
>>> Ubuntu 16.04 will ship with Java 8 and that will be the next LTS.
>>>
>>> Wido
>>>
>>> On 01-May-2015, at 4:07 pm, Wilder Rodrigues
>>> <wrodrig...@schubergphilis.com<mailto:wrodrig...@schubergphilis.com><m
>> ailto:wrodrig...@schubergphilis.com>
>>>
>>>
>>>
>>>
>>> wrote:
>>>
>>> Hi Marcus,
>>>
>>> Sorry for the push, I think after doing the whole
>>> CitrixResourceBase refactor I also got a bit attached to the whole
>>> thing/solution. ;)
>>>
>>> Thanks for the input you gave. I will finish the refactor and apply
>>> it to both implementations.
>>>
>>> Cheers, Wilder
>>>
>>>
>>> On 01 May 2015, at 09:06, Marcus
>>> <shadow...@gmail.com<mailto:shadow...@gmail.com><mailto:shadowsor@gmai
>> l.com><mailto:shadowsor@gm
>>>
>>>
>> ai
>>>
>>>
>>> l.com<http://l.com>>> wrote:
>>>
>>> Oh, and of course the annotation added to the wrapper looks like:
>>>
>>>
>>> ...
>>>
>>> @ResourceWrapper(handles =  CheckHealthCommand.class)
>>>
>>> public final class LibvirtCheckHealthCommandWrapper
>>>
>>> ...
>>>
>>>
>>> maybe 'wraps' or 'wrapperfor' would be better than 'handles' in
>>> your naming scheme. You get the idea.
>>>
>>> On Thu, Apr 30, 2015 at 11:59 PM, Marcus
>>> <shadow...@gmail.com<mailto:shadow...@gmail.com><mailto:shadowsor@gmai
>> l.com>>
>>> wrote: I agree, this wrapper is a good step forward. It's totally
>>> fine to continue on that path because it is obviously better and
>>> makes it easy to switch to autodetection anytime later by simply
>>> adding the annotation. Sorry if I got a bit passionate about that,
>>> but as you mention I also get tired of adding things in multiple
>>> places, and the annotations have worked well in the API and provide
>>> a good model to emulate for consistency.
>>>
>>> I can't share code, because these extensions to
>>> LibvirtComputingResource that I've provided for other companies
>>> have not been open sourced. I can speak more generically though
>>> about methods.
>>>
>>> To answer question "a", reflection allows you to do something
>>> like:
>>>
>>> Reflections reflections = new
>>> Reflections("com.cloud.hypervisor.kvm.resource.wrapper");
>>> Set<Class<? extends CommandWrapper>> wrappers =
>>> reflections.getSubTypesOf(CommandWrapper.class);
>>>
>>> So here in "new Reflections" we are automatically filtering for
>>> just the wrappers that would apply to the KVM plugin. Then to
>>> finish it off, you iterate through the wrappers and do:
>>>
>>> ResourceWrapper annotation =
>>> wrapper.getAnnotation(ResourceWrapper.class);
>>> citrixCommands.put(annotation.handles(), wrapper.newInstance());
>>>
>>> Sorry, I guess that's four lines, plus the relevant for loop. And
>>> probably a null check or something for the annotation. You also
>>> have to add the annotation class itself, and add a line for the
>>> annotation in each wrapper, but in the end when we add new
>>> Commands, we won't have to touch anything but the new class that
>>> handles the command.
>>>
>>>
>>> public @interface ResourceWrapper {
>>>
>>> Class<? extends Command> handles();
>>>
>>> }
>>>
>>> There's an example of something similar to this in
>>> KVMStoragePoolManager.java (annotation is StoragePoolInfo.java).
>>> This example has actually been adapted from that. Also to a lesser
>>> extent in the API server, but it is spread across a bunch of
>>> classes.
>>>
>>> On Thu, Apr 30, 2015 at 10:41 PM, Wilder Rodrigues
>>> <wrodrig...@schubergphilis.com<mailto:wrodrig...@schubergphilis.com><m
>> ailto:wrodrig...@schubergphilis.com>
>>>
>>>
>>>
>>>
>>> wrote: Hi Marcus,
>>>
>>> Thanks for the email… I’m always in for improvements. But why can’t
>>> you share the code?
>>>
>>> Few points below:
>>>
>>> 1. I added an subclassing example of LibvirtComputingResource
>>> because you mentioned it in a previous email:
>>>
>>> On 23 Apr 2015, at 17:26, Marcus
>>> <shadow...@gmail.com<mailto:shadow...@gmail.com><mailto:shadowsor@gmai
>> l.com>>
>>> wrote:
>>>
>>> I mentioned the reflection model because that's how I tend to
>>> handle the commands when subclassing LibvirtComputingResource.
>>>
>>> 2. Current situation with LibvirtComputingResource on Master is:
>>>
>>> a. 67 IFs b. 67 private/protected methods that are used only there
>>> c. If a new Command is added it means we will have a new IF and a
>>> new private method e. Maintenance is hell, test is close to zero
>>> and code quality is below expectations
>>>
>>> That being said, the main idea with the refactor is to change
>>> structure only, not behaviour. So what I’m doing is to simply move
>>> the code out the LibvirtCompRes and write tests for it, keeping the
>>> behaviour the same - to be done in a next phase. If you look at the
>>> changes you will see that some wrappers are already 100% covered.
>>> However, some others have 4% or 8% (not that much though). I would
>>> like to refactor that as well, but that could change behaviour
>>> (mentioned above) which I don’t want to touch now.
>>>
>>> 3. With the new situation:
>>>
>>> a. No IFs b. All methods wrapped by other classes (command
>>> wrappers) - loosely coupled, easier to test and maintain c. If a
>>> new Command is added we would have to add a command wrapper and 1
>>> line in the request wrapper implementation ( I know, it hurts you a
>>> bit) - but please bear with me for the good news.
>>>
>>> 4. the warnings are due to that: Hashtable<Class<? extends
>>> Command>, CommandWrapper>()
>>>
>>> No big deal.
>>>
>>> As I understood from  your first paragraph we would have to
>>> annotated the commands classes, right? I mean, all of them.
>>>
>>> That’s something I wouldn’t do in this phase, to be honest. It
>>> might seem harmless to do, but I like to break things down a bit
>>> and have more isolation in my changes.
>>>
>>> What’s next: I will finish the refactor with the request wrapper as
>>> it is. For me it is no problem do add the lines now and remove them
>>> in 1 week. Most of the work is concentrated in the tests, which I’m
>>> trying as hard as I can to get them in the best way possible. Once
>>> it’s done and pushed to master, I will analyse what we would need
>>> to apply the annotation.
>>>
>>> But before I go to bring the kids to school, just one question:
>>>
>>> a. The “handle” value, in the annotation, would have the wrapper
>>> class that would be used for that command, right?  Now let’s get 1
>>> command as example: CheckHealthCommand. Its wrapper implementation
>>> differs per hypervisor (just like all the other wrapper commands
>>> do). I’m not taking the time to really think about it now, but how
>>> would we annotated the different wrappers per command?
>>>
>>> Thanks again for your time.
>>>
>>> Cheers, Wilder
>>>
>>>
>>> On 30 Apr 2015, at 22:52, Marcus
>>> <shadow...@gmail.com<mailto:shadow...@gmail.com><mailto:shadowsor@gmai
>> l.com>>
>>> wrote:
>>>
>>> Ok. I wish I could share some code, because it isn't really as big
>>> of a deal as it sounds from your reasoning. It is literally just 3
>>> lines on startup that fetch anything with the '@AgentExecutor'
>>> annotation and stores it in a hash whose key is the value from
>>> @AgentExecutor's 'handles' property. Then when a *Command comes it
>>> it is passed to the appropriate Executor class.
>>>
>>> Looking at CitrixRequestWrapper, the 3 lines I mention are almost
>>> identical in function to your init method, just that it uses the
>>> annotation to find all of the commands, rather than hardcoding
>>> them. We use the same annotation design for the api side of the
>>> code on the management server, which allows the api commands to be
>>> easier to write and self-contained (you don't have to update other
>>> code to add a new api call). It makes things easier for novice
>>> developers.
>>>
>>> This implementation is no less typesafe than the previous design
>>> (the one with all of the instanceof). It didn't require any casting
>>> or warning suppression, either, as the wrapper does.
>>>
>>> Extending LibvirtComputingResource is not ideal, and doesn't work
>>> if multiple third parties are involved. Granted, there hasn't been
>>> a lot of demand for this, nevertheless it's particularly important
>>> for KVM, where the Command classes are executed on the hypervisor
>>> it's not really feasible to just dump the code in your management
>>> server-side plugin like some plugins do.
>>>
>>> In reviewing the code, the two implementations are really very
>>> close. If you just updated init to fetch the wrappers based on
>>> either an annotation or the class they extend, or something along
>>> those lines so this method doesn't have to be edited every time a
>>> command is added, that would be more or less the same thing. The
>>> the KVM agent would be pluggable like the management server side
>>> is.
>>>
>>> On Thu, Apr 30, 2015 at 12:55 PM, Wilder Rodrigues
>>> <wrodrig...@schubergphilis.com<mailto:wrodrig...@schubergphilis.com><m
>> ailto:wrodrig...@schubergphilis.com>
>>>
>>>
>>>
>>>
>>> wrote: Hi Marcus,
>>>
>>> Apologies for taking so much time to reply to your email, but was,
>>> and still am, quite busy. :)
>>>
>>> I would only use reflection if that was the only way to do it. The
>>> use of reflection usually makes the code more complex, which is not
>>> good when we have java developers in all different levels (from jr.
>>> do sr) working with cloudstack. It also makes us lose the type
>>> safety, which might also harm the exception handling if not done
>>> well. In addition, if we need to refactor something, the IDE is no
>>> longer going to do few things because the refection code cannot be
>>> found.
>>>
>>> If someone will need to extend the LibvirtComputingResource that
>>> would be no problem with the approach I’m using. The
>>> CitrixResourceBase also has quite few sub-classes and it works just
>>> fine.
>>>
>>> I will document on the wiki page how it should be done when
>>> sub-classing the LibvirtComputingResource class.
>>>
>>> In a quick note/snippet, one would do:
>>>
>>> public class EkhoComputingResource extends LibvirtComputingResource
>>> {
>>>
>>> @Override public Answer executeRequest(final Command cmd) {
>>>
>>> final LibvirtRequestWrapper wrapper =
>>> LibvirtRequestWrapper.getInstance(); try { return
>>> wrapper.execute(cmd, this); } catch (final Exception e) { return
>>> Answer.createUnsupportedCommandAnswer(cmd); } } }
>>>
>>>
>>> In the flyweight where I keep the wrapper we could have ():
>>>
>>> final Hashtable<Class<? extends Command>, CommandWrapper>
>>> linbvirtCommands = new Hashtable<Class<? extends Command>,
>>> CommandWrapper>(); linbvirtCommands.put(StopCommand.class, new
>>> LibvirtStopCommandWrapper());
>>>
>>> final Hashtable<Class<? extends Command>, CommandWrapper>
>>> ekhoCommands = new Hashtable<Class<? extends Command>,
>>> CommandWrapper>(); linbvirtCommands.put(StopCommand.class, new
>>> EkhoStopCommandWrapper());
>>>
>>> resources.put(LibvirtComputingResource.class, linbvirtCommands);
>>> resources.put(EkhoComputingResource.class, ekhoCommands);
>>>
>>> But that is needed only if the StopCommand has a different
>>> behaviour for the EkhoComputingResource.
>>>
>>> Once a better version of the documentation is on the wiki, I will
>>> let you know.
>>>
>>> On other matters, I’m also adding unit tests for all the changes.
>>> We already went from 4% to 13.6% coverage in the KVM hypervisor
>>> plugin. The code I already refactored has 56% of coverage.
>>>
>>> You can see all the commits here:
>>> https://github.com/schubergphilis/cloudstack/tree/refactor/libvirt_r
>>>
>>>
>> es
>>>
>>>
>>> ource
>>>
>>> Cheers, Wilder
>>>
>>> On 23 Apr 2015, at 17:26, Marcus
>>> <shadow...@gmail.com<mailto:shadow...@gmail.com><mailto:shadowsor@gmai
>> l.com>>
>>> wrote:
>>>
>>> Great to see someone working on it. What sorts of roadblocks came
>>> out of reflection? How does the wrapper design solve the
>>> pluggability issue? This is pretty important to me, since I've
>>> worked with several companies now that end up subclassing
>>> LibvirtComputingResource in order to handle their own Commands on
>>> the hypervisor from their server-side plugins, and changing their
>>> 'resource' to that in agent.properties. Since the main agent class
>>> needs to be set at agent join, this is harder to manage than it
>>> should be.
>>>
>>> I mentioned the reflection model because that's how I tend to
>>> handle the commands when subclassing LibvirtComputingResource. I
>>> haven't had any problems with it, but then again I haven't tried to
>>> refactor 5500 lines into that model, either.
>>>
>>> On Thu, Apr 23, 2015 at 1:17 AM, Wilder Rodrigues
>>> <wrodrig...@schubergphilis.com<mailto:wrodrig...@schubergphilis.com><m
>> ailto:wrodrig...@schubergphilis.com>
>>>
>>>
>>>
>>>
>>> wrote:
>>>
>>> Hi Marcus,
>>>
>>> I like the annotation idea, but reflection is trick because it
>>> hides some information about the code.
>>>
>>> Please, have a look at the CitrixResourceBase after the refactor I
>>> did. It became quite smaller and test coverage was improved.
>>>
>>> URL:
>>> https://cwiki.apache.org/confluence/display/CLOUDSTACK/Refactoring+X
>>>
>>>
>> en
>>>
>>>
>>> Server+Hypervisor+Plugin
>>>
>>> The same patter is being about to Libvirt stuff. The coverage on
>>> the KVM hypervisor plugin already went from 4 to 10.5% after
>>> refactoring 6 commands
>>>
>>> Cheers, Wilder
>>>
>>> On 22 Apr 2015, at 23:06, Marcus
>>> <shadow...@gmail.com<mailto:shadow...@gmail.com><mailto:shadowsor@gmai
>> l.com>>
>>> wrote:
>>>
>>> Kind of a tangent, but I'd actually like to see some work done to
>>> clean up LibvirtComputing resource. One model I've prototyped that
>>> seems to work is to create an annotation, such as
>>> 'KVMCommandExecutor', with a 'handles' property. With this
>>> annotation, you implement a class that handles, e.g. StartCommand,
>>> etc. Then in LibvirtComputingResource, the 'configure' method
>>> fetches all of these executors via reflection and stores them in an
>>> object. Then, instead of having all of the 'instanceof' lines in
>>> LibvirtComputingResource, the executeRequest method fetches the
>>> executor that handles the incoming command and runs it.
>>>
>>> I think this would break up LibvirtComputingResource into smaller,
>>> more testable and manageable chunks, and force things like config
>>> and utility methods to move to a more sane location, as well. As a
>>> bonus, this model makes things pluggable. Someone could ship KVM
>>> plugin code containing standalone command executors that are
>>> discovered at runtime for things they need to run at the hypervisor
>>> level.
>>>
>>> On Tue, Apr 21, 2015 at 6:27 AM, Wilder Rodrigues
>>> <wrodrig...@schubergphilis.com<mailto:wrodrig...@schubergphilis.com><m
>> ailto:wrodrig...@schubergphilis.com>
>>>
>>>
>>>
>>>
>>> wrote:
>>>
>>> Hi all,
>>>
>>> Yesterday I started working on the LibvirtComputingResource class
>>> in order to apply the same patterns I used in the
>>> CitrixResourceBase + add more unit tests to it After 10 hours of
>>> work I got a bit stuck with the 1st test, which would cover the
>>> refactored LibvirtStopCommandWrapper. Why did I get stuck? The
>>> class used a few static methods that call native libraries, which I
>>> would like to mock. However, when writing the tests I faced
>>> problems with the current Mockito/PowerMock we are using: they are
>>> simply not enough for the task.
>>>
>>> What did I do then? I added a dependency to EasyMock and
>>> PowerMock-EasyMock API. It worked almost fine, but I had to add a
>>> “-noverify” to both my Eclipse Runtime configuration and also to
>>> the cloud-plugin-hypervisor-kvm/pom.xml file. I agree that’s not
>>> nice, but was my first attempt of getting it to work. After trying
>>> to first full build I faced more problems related to
>>> ClassDefNotFoundExpcetion which were complaining about Mockito
>>> classes. I then found out that adding the PowerMockRunner to all
>>> the tests classes was going to be a heavy burden and would also
>>> mess up future changes (e.g. the -noverify flag was removed from
>>> Java 8, thus adding it now would be a problem soon).
>>>
>>> Now that the first 2 paragraphs explain a bit about the problem,
>>> let’s get to the solution: Java 8
>>>
>>> The VerifyError that I was getting was due to the use of the latest
>>> EasyMock release (3.3.1). I tried to downgrade it to 3.1/3.2 but it
>>> also did not work. My decision: do not refactor if the proper tests
>>> cannot be added. This left me with one action: migrate to Java 8.
>>>
>>> There were mentions about Java 8 in february[1] and now I will put
>>> some energy in making it happen.
>>>
>>> What is your opinion on it?
>>>
>>> Thanks in advance.
>>>
>>> Cheers, Wilder
>>>
>>> http://mail-archives.apache.org/mod_mbox/cloudstack-dev/201502.mbox/
>>>
>>>
>> %3
>>>
>>>
>>> c54eef6be.5040...@shapeblue.com<mailto:c54eef6be.5040...@shapeblue.com
>>> %3E<http://mail-archives.apache.org/mod_m
>>>
>>>
>> box/cloudstack-dev/201502.mbox/<54eef6be.5040...@shapeblue.com<mailto:54
>> eef6be.5040...@shapeblue.com><mailto
>>> :54
>>>
>>>
>>> eef6be.5040...@shapeblue.com<mailto:eef6be.5040...@shapeblue.com>>>>
>>>
>>>  Regards, Rohit Yadav Software Architect, ShapeBlue
>>>
>>>
>>> [cid:9DD97B41-04C5-45F0-92A7-951F3E962F7A]
>>>
>>>
>>> M. +91 88 262 30892 |
>>> rohit.ya...@shapeblue.com<mailto:rohit.ya...@shapeblue.com><mailto:roh
>> it.ya...@shapeblue.com>
>>>
>>>
>> Blog: bhaisaab.org<http://bhaisaab.org><http://bhaisaab.org> | Twitter:
>> @_bhaisaab
>>>
>>>
>>>
>>>
>>> Find out more about ShapeBlue and our range of CloudStack related
>>> services
>>>
>>> IaaS Cloud Design &
>>> Build<http://shapeblue.com/iaas-cloud-design-and-build//> CSForge –
>>> rapid IaaS deployment framework<http://shapeblue.com/csforge/>
>>> CloudStack
>>> Consulting<http://shapeblue.com/cloudstack-consultancy/> CloudStack
>>> Software
>>> Engineering<http://shapeblue.com/cloudstack-software-engineering/>
>>>
>>>
>>> CloudStack Infrastructure
>>> Support<http://shapeblue.com/cloudstack-infrastructure-support/>
>>>
>>>
>>> CloudStack Bootcamp Training
>>> Courses<http://shapeblue.com/cloudstack-training/>
>>>
>>> This email and any attachments to it may be confidential and are
>>> intended solely for the use of the individual to whom it is
>>> addressed. Any views or opinions expressed are solely those of the
>>> author and do not necessarily represent those of Shape Blue Ltd or
>>> related companies. If you are not the intended recipient of this
>>> email, you must neither take any action based upon its contents,
>>> nor copy or show it to anyone. Please contact the sender if you
>>> believe you have received this email in error. Shape Blue Ltd is a
>>> company incorporated in England & Wales. ShapeBlue Services India
>>> LLP is a company incorporated in India and is operated under
>>> license from Shape Blue Ltd. Shape Blue Brasil Consultoria Ltda is
>>> a company incorporated in Brasil and is operated under license from
>>> Shape Blue Ltd. ShapeBlue SA Pty Ltd is a company registered by The
>>> Republic of South Africa and is traded under license from Shape
>>> Blue Ltd. ShapeBlue is a registered trademark.
>>>
>>>
>>>
>>> Find out more about ShapeBlue and our range of CloudStack related
>>> services
>>>
>>> IaaS Cloud Design &
>>> Build<http://shapeblue.com/iaas-cloud-design-and-build//> CSForge
>>> – rapid IaaS deployment framework<http://shapeblue.com/csforge/>
>>> CloudStack Consulting<http://shapeblue.com/cloudstack-consultancy/>
>>> CloudStack Software
>>> Engineering<http://shapeblue.com/cloudstack-software-engineering/>
>>> CloudStack Infrastructure
>>> Support<http://shapeblue.com/cloudstack-infrastructure-support/>
>>> CloudStack Bootcamp Training
>>> Courses<http://shapeblue.com/cloudstack-training/>
>>>
>>> This email and any attachments to it may be confidential and are
>>> intended solely for the use of the individual to whom it is
>>> addressed. Any views or opinions expressed are solely those of the
>>> author and do not necessarily represent those of Shape Blue Ltd or
>>> related companies. If you are not the intended recipient of this
>>> email, you must neither take any action based upon its contents,
>>> nor copy or show it to anyone. Please contact the sender if you
>>> believe you have received this email in error. Shape Blue Ltd is a
>>> company incorporated in England & Wales. ShapeBlue Services India
>>> LLP is a company incorporated in India and is operated under
>>> license from Shape Blue Ltd. Shape Blue Brasil Consultoria Ltda is
>>> a company incorporated in Brasil and is operated under license
>>> from Shape Blue Ltd. ShapeBlue SA Pty Ltd is a company registered
>>> by The Republic of South Africa and is traded under license from
>>> Shape Blue Ltd. ShapeBlue is a registered trademark.
>>>
>>>
>>>
> 
> Find out more about ShapeBlue and our range of CloudStack related services
> 
> IaaS Cloud Design & Build<http://shapeblue.com/iaas-cloud-design-and-build//>
> CSForge – rapid IaaS deployment framework<http://shapeblue.com/csforge/>
> CloudStack Consulting<http://shapeblue.com/cloudstack-consultancy/>
> CloudStack Software 
> Engineering<http://shapeblue.com/cloudstack-software-engineering/>
> CloudStack Infrastructure 
> Support<http://shapeblue.com/cloudstack-infrastructure-support/>
> CloudStack Bootcamp Training 
> Courses<http://shapeblue.com/cloudstack-training/>
> 
> This email and any attachments to it may be confidential and are intended 
> solely for the use of the individual to whom it is addressed. Any views or 
> opinions expressed are solely those of the author and do not necessarily 
> represent those of Shape Blue Ltd or related companies. If you are not the 
> intended recipient of this email, you must neither take any action based upon 
> its contents, nor copy or show it to anyone. Please contact the sender if you 
> believe you have received this email in error. Shape Blue Ltd is a company 
> incorporated in England & Wales. ShapeBlue Services India LLP is a company 
> incorporated in India and is operated under license from Shape Blue Ltd. 
> Shape Blue Brasil Consultoria Ltda is a company incorporated in Brasil and is 
> operated under license from Shape Blue Ltd. ShapeBlue SA Pty Ltd is a company 
> registered by The Republic of South Africa and is traded under license from 
> Shape Blue Ltd. ShapeBlue is a registered trademark.
> 

Reply via email to