Monday, August 24, 2015

The End of Summer

  I'm sad to say that the summer is goes to the end... yes, everyone knows that (or don't you?). But this means also that my internship in moVirt project is goes to the end too. And I'm really sad, that I can't continue working with this project. I'd love to list it as my full time job, but now I have to find something new and I'm eager to learn new technologies to work with.
  I'm happy that I chose moVirt among Outreachy projects. For the first time I thought that I can pretend only for some PHP project, maybe with JavaScript, because it was the most familiar for me at that moment. But I thought it could be the most boring thing, and I saw moVirt - Android project on Java. I also had Java experience but never in context of Android development. In fact I also had never touch real android phone or tablet. As later my mentor will say in sarcasm that this is good prerequisites for android development :) But I decided that I could learn Android development in one day.
Pic. 1. I know Android.

  Well, it was not really a one day, I've spent a half of week to read 101 basis and I've been learning new concepts of Android development in depth constantly through the whole internship. And this is the best part, when you can learn while work, and moVirt is complex project which doesn't ends on android, it also includes some technologies that I also learned, for example client-server pattern. REST API, database querying, etc. Also I have installed Linux for the first time, and now I'm not hating git :)

  Actually I may continue contributing to moVirt project after internship, because it's open-source project, and I have some plans, but it would be possible only as a volunteer. And thanks to Outreachy I think I have much more chance to find a new job that I want because of all that experience I gained during this summer.

Thursday, August 6, 2015

Google Play release!

  Since the previous 0.2beta release only one week passed by and suddenly we now have 1.0 version which is released on Google Play Store!

  This week was quite intensive even our mentor now actively contributes, not just code reviewing. My main feature for 1.0 version was to add support for Migrate VM action. This task includes new concepts of moVirt that I've still been not familiar with - which one is REST API.

  REST is used to perform communication between server and clients (oVirt and moVirt in this case). Briefly, you can post data or actions from client to add or perform them on server; or acquire for entities, stored on the server. At that point moVirt already had some actions like: start, stop, reboot VM, etc. My task was simply to extend current interface with one new action. But migration was a bit more complex, because it has options inside Action entity where you can set the destination host to migrate VM, or leave it empty to migrate to default host. After spending some time learning about REST and JSON, I've made new class that extends empty Action with destination host option, and it looks simply like this:
@JsonRootName("action")
@JsonIgnoreProperties(ignoreUnknown = true)
public class ActionMigrate extends Action {

    public Host host;

    public ActionMigrate(String hostId) {
        host = new Host();
        host.id = hostId;
    }
}
   After REST part has been made we need UI to run it. Important part is to show user the list of available hosts to choose. And because I'm not experienced user of Android, I've been thinking in concept that such choices made through dialogue windows. And I've started to read guides about dialogues in Android. I found that AlertDialogue may perfectly fit the requirements, because it supports lists with items to choose which are loaded from database. And after I finally made clean and reliably class to show this dialogue, we found that list doesn't support scrolling so only first 4 items shows! I haven't seen any warning in SDK documentations and guides that this dialogue shows only first 4 items. What a shame...
 
  There was several ways to fix this, but I decided to transform from dialogue to activity, and set layout from scratch, and as a result it now looks even better.
Pic. 1. Migrate VM activity.

Wednesday, July 29, 2015

New MoVirt release - introduction of augmented reality

  I decided to date this post for MoVirt release and since release has been delayed this post is delayed too.

  But now 0.2 beta version of MoVirt is available to everyone, and I'm very happy about this because the main feature introduced in this version is my work on augmented reality! You can check how does it work in this video:

  Also you can download latest test build for Android from here if you are using oVirt or interested in virtualization. This is unsigned package, so you need to copy .apk file into your android device, enable "Unknown sources" in Settings and install .apk file.

  To prepare this release I've spent three weeks fixing various bugs, stability and usability issues along with refactoring and cleaning some parts of the code. And there were two "interesting" tasks which annoyed me a lot.

  The first task was about android synchronization. We noticed that automatic synchronization with oVirt server happens only once a day and this may be not very good behavior for monitoring software, because you can easily skip some important events if you are relying on notifications from moVirt. According to android SDK documentation:
When a network connection is available, the Android system sends out a message every few seconds to keep the device's TCP/IP connection open. This message also goes to the ContentResolver of each app. By calling setSyncAutomatically(), you can run the sync adapter whenever the ContentResolver receives the message.
"every few seconds", but this is not working in moVirt for some reason. People at stackoverflow.com says that android documentation misguiding in some topics especially about synchronization, and I found the only working solution is to enable periodic sync with fixed custom interval which is not recommended. There is one more solution (which is possibly the best) is to use push-notifications via GCM, but this is far-far future plans which requires modification also in oVirt server.

  The second task was about proper storing time in database. Since we have information at what time connection to server was lost and when was the last successful synchronization, we need to store this information in database to share between activities and sessions (detailed about necessity of using database in previous post). My first thought was to use java.sql.Timestamp class because it specially designed to store time and date in database. As I understand this class contains Unix Time which is UTC time and converts to properly formatted string to store in database.
public String toString()
Formats a timestamp in JDBC timestamp escape format. yyyy-mm-dd hh:mm:ss.fffffffff, where ffffffffff indicates nanoseconds.
Everything was looking fine until I realized that time in database stored in local time zone! And if you change time zone in your device it will show wrong time. Who in the world needs to store date and time in database in local time zone? And why does this Timestamp class do this conversion implicitly in toString() function with no obvious way to avoid this conversion? Ok, there are LOTS of other classes to work with time in java, and I decided to find some ready to use code snippets to store time as string in database in UTC... I've spent three days trying different solutions and all of them was wrong and shows the wrong time, because every class in Java performs implicit time zone conversion even if it is not needed and not obvious for this action. So I stopped to store time in database just as Unix Time and convert to string only while displaying and this seems to work.

Wednesday, July 8, 2015

More ways to help

  Hello again, it's time for a blog today!

  So it's my 7th week along with moVirt, as I said previously I have finished with my feature which was to implement  AR in moVirt. In past two weeks I've been focused on bug fixes, requests from users and other improvements which should make moVirt more stable and friendly to the users.

  The first task was to add notifications about Internet connection which came from user request. It's very important to keep user informed about connection state and how information is old while you work with remote data. So we decided just to put simple icon that warns if sync request was failed and Internet connection lost. "Looks like quite simple task with few lines of code" - what I was thinking. The first thing that I realized about android applications, that it's not that simple to keep application scope data if you have more that one activity and one of appropriate way to share some piece of information between all the activities is to put it into database. Well, ok, I'm familiar with SQL, and there is guides inside Android SDK documentation how to perform actions with SQLite. But if you are developing inside big enough project like moVirt then you find that it uses couple of frameworks and classes that hides low-level actions and I just can't connect to DB and insert a record into table. And I stepped into stupid situation where high-level concept confuses more then low-level. Hopefully my mentor guided me through part of the maze of classes and frameworks. And all this misadventures just to save a one variable available across all the activities. So the next step was to put an icon... into every activity in app. I thought: "Oh no, do I really need to copy&past code across all the activities?" I was about to start blaming Google for this Activity concept, but actually there are a couple of techniques to share logic and views between different activities: you can use fragments or overlays, but the best solution with minimal copy&pasting is to inherit activities! I'm quite experienced in OOP, but I haven't realized that we can inherit activities, before my mentor suggested this to me. Even though this trick requires significant refactoring, but it has lots of advantages. Following this solution and implemented parent activity as super class now we can add any code in one place in it would automatically work in every activity. After adding connection warning icon into parent activity I also grabbed sync action button to appear on every screen and now we can sync everywhere! And there could be even more things to appear in every activity.

  Yet another task was to extend moVirt's notification system. Since we now have connection state, information, we can inform user about failed synchronizations via android notifications. And since it was me who created NotificationHelper class (during initial contribution) adding new notifications is the easiest part.

  There were a couple of small fixes which I don't want to concentrate on. The last thing I want to write is about testing. My mentor insists that we need implement some unit tests for moVirt project, so that project may become more stable and bugless, and I agree with him, since I was interested in unit testing and this tasks now assigned to me. However my first attempts was failed. Android is not that simple to write unit tests, especially if you are not following TDD from beginning. But we'll see what I can do in the next two weeks.


Pic. 1. Foretasting of unit testing.

Friday, June 26, 2015

Becoming linux user

  Well, I delayed this post for few days, because I was busy with patches for moVirt and switching tasks in the middle is not good... But now I have time and there are important news I want to share.

  First thing that happened in last 2 weeks is that I finished with all base Augmented Reality features for moVirt. Now when you look at barcode you'll see information about host (status, CPU and memory usage), host events on right panel and host VMs on left panel. Also there is a button to open host details page where you could perform different actions with this host and VMs. The hardest thing is to optimize layout for variety of screen sizes and screen resolutions. On my 10" tablet all panels fits perfectly, but for smaller screens we need new design ideas.
Pic. 1. First look of AR screen with all base features.
  Second thing is that I'm Linux user now. For long time I've been avoiding this OS, but now it's time! To test moVirt features I need working setup of oVirt. Since oVirt is a linux software I need it running somewhere. For some time I've been using oVirt LiveCD booted from USB flash on my second laptop, until USB ports stopped working. I was looking for different solutions like running LiveCD .iso from HDD and from virtual machine and I realize that I need proper linux installation on my machine. I don't want to go deep with details, saying only that this way was also full of difficulties. To everyone how will try to install linux: don't try any optional solutions, follow only default, the most simple installation. You see that there is an option to install from .iso on hdd, and there is article in documetation? Don't try this, no one have tested this, you will be covered with bugs. You heard that there is no problem installing linux near windows installation? Don't trust them, erase your entire HDD (don't forget to backup...) and make a clean installation. Otherwise you will step into some bugs and lost dozens of hours.
Pic. 2. Meet the linux.
  After getting over through the troubles I was ready to install real oVirt engine, but with fake VDSM, because for testing purpose I don't need real hosts and VMs. In addition to the guide provided on the web-site we need few more steps:
1. Configure settings in database with this commands
psql engine -U postgres -c "UPDATE vdc_options set option_value = 'false' where option_name = 'SSLEnabled'"
psql engine -U postgres -c "UPDATE vdc_options set option_value = 'false' where option_name = 'EncryptHostCommunication'"
psql engine -U postgres -c "UPDATE vdc_options set option_value = 'false' where option_name = 'InstallVds'"

2. Uncheck "JSON Protocol" while creating host in web admin.

After that it was possible to create fake hosts and VMs to test moVirt.


Monday, June 8, 2015

First commit

  Two weeks passed and right at this point I've made pull request to moVirt repo with my commit. It's not actually "first" commit, there was several of them before the internship starts. And what I want to tell here is Git... I thought that I finally understand how to work with Git with help of my mentor during work on initial commit to apply to Outreachy. But on Friday I was confused and very frustrated again. The idea was to leave all day-by-day commits in my fork (so I could trace my progress later if I'll need to revert something), and send squashed version into main repo to ease reviewing. All my attempts was failed,.. seems like Git tries to reduce all redundancy. So then I decided to create patch which would contain all my commits in single file, then I erased everything in my repo because there was a lot of garbage of branches and merges, and just to avoid redundancy if Git decided just to link to previous commits instead of recreating them from patch, and last step was to apply patch... But who in the world could ever know that applying patch with multiple commits in it leads to reverted order of commits! I was one step before loosing everything I've done during this two weeks. Hopefully I've managed to recreate my progress from reversed commits on the weekend, and also I've made some fixes that I've forgotten before committing.

  So lets leave that freaky unhuman Git and get back to the commit. First thing I've realized learning ZXing that it doesn't assume to be used as a library inside another app. The integration class just makes calls to another app Barcode Scanner (BS) with it's own UI, thus preventing us from drawing any overlays on camera screen. Hopefully BS is a part of ZXing and also Apache licensed, so I've taken all decoder classes and build my own Activity class based on BS's Activity, so that we could decorate camera screen as we like. Also it could improve response time, because we don't need to support all barcodes, just choose one of them and skip guessing time.

  Looking through BS's Activity I've partially learned how parallel threads and handlers works in android. Activity has it's handler which loops through the message queue. Decoder works on another thread and posts messages when barcode has been detected and decoded. While catching such messages we could interact with Activity. All interactions occurs in function handleDecode(...), here we could ask data provider for Host instance which we are looking at, and show any desired information on screen. Also there is viewfinderView class that suits to draw anything on to the screen with Paint and Canvas classes. At this point I've made just simple rectangle that rounds decoded barcode in real-time to mark which one has been decoded if there are several of them on screen.

  Only two weeks (or less) required to bring Augmented Reality support with barcodes into your app. It may look not so fancy, but functional enough. And could be easily extended.

Pic.1. Test view with some fake data.

Tuesday, May 26, 2015

Internship starts!

  Yesterday was my first work day in Outreachy Program under moVirt project, so I'm starting this blog to share my progress and experience during my internship which will lasts the whole summer. I'm gonna post once every two weeks and will write about what have happened during those two weeks.

  As this is my first post and work only begins I'll mark here my plans with moVirt project. The main feature which I'm about to implement it is augmented reality for moVirt which will help maintain servers running oVirt. The point is to mark every server with sticker with some graphical code such as Data Matrix or QR-code (barcode), then focus camera of your smartphone or tablet and you'll see info about virtual machines running on this current host you are looking at.

  My first task was to find any appropriate lib for Android device which will handle barcode processing and suitable to implement inside moVirt app. My eye falls on ZXing Library, it perfectly fits requirements:
  • it could be integrated into android app
  • it's free and open-source under Apache licence
  • it supports many types of barcodes so we can switch between them if necessary

  During upcoming days I'm gonna study documentation for this lib find some examples and tutorials. Also I will try to write some test code for moVirt.