com.abiquo.vsm.migration.Migrator.java Source code

Java tutorial

Introduction

Here is the source code for com.abiquo.vsm.migration.Migrator.java

Source

/**
 * Abiquo community edition
 * cloud management application for hybrid clouds
 * Copyright (C) 2008-2010 - Abiquo Holdings S.L.
 *
 * This application is free software; you can redistribute it and/or
 * modify it under the terms of the GNU LESSER GENERAL PUBLIC
 * LICENSE as published by the Free Software Foundation under
 * version 3 of the License
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * LESSER GENERAL PUBLIC LICENSE v.3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

package com.abiquo.vsm.migration;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;

import com.abiquo.vsm.model.PhysicalMachine;
import com.abiquo.vsm.model.VirtualMachine;
import com.abiquo.vsm.model.VirtualMachinesCache;
import com.abiquo.vsm.monitor.Monitor.Type;
import com.abiquo.vsm.redis.dao.RedisDao;
import com.abiquo.vsm.redis.dao.RedisDaoFactory;

public class Migrator {
    private final static Logger logger = LoggerFactory.getLogger(Migrator.class);

    public final static String MachineListKey = "tomigrate";

    private String host;

    private int port;

    private int database;

    private int machinesCount;

    private int subscriptionsCount;

    private Map<String, Integer> ports;

    private Map<String, Type> hypervisors;

    public Migrator(String host, int port, int database) {
        this.host = host;
        this.port = port;
        this.database = database;

        this.machinesCount = 0;
        this.subscriptionsCount = 0;

        this.ports = new HashMap<String, Integer>();
        this.ports.put(Type.VMX_04.name(), 443);
        this.ports.put(Type.HYPERV_301.name(), 5985);
        this.ports.put(Type.KVM.name(), 8889);
        this.ports.put(Type.VBOX.name(), 8889);
        this.ports.put(Type.XEN_3.name(), 8889);
        this.ports.put(Type.XENSERVER.name(), 9363);

        this.hypervisors = new HashMap<String, Type>();
        this.hypervisors.put("vmx-04", Type.VMX_04);
        this.hypervisors.put("xenserver", Type.XENSERVER);
        this.hypervisors.put("xen-3", Type.XEN_3);
        this.hypervisors.put("hyperv-301", Type.HYPERV_301);
    }

    public void migratePersistedModel() {
        RedisWrapper wrapper = new RedisWrapper(host, port, database);
        RedisDao dao = RedisDaoFactory.getInstance();

        for (String id : wrapper.getAllSubscriptionIds()) {
            String address = wrapper.getHypervisorUrl(id);
            String type = wrapper.getHypervisorType(id);
            String username = wrapper.getUser(id);
            String password = wrapper.getPassword(id);
            String virtualMachineName = wrapper.getVirtualSystemId(id);

            PhysicalMachine machine = insertMachine(dao, address, type, username, password);

            if (machine != null) {
                VirtualMachine virtualMachine = dao.findVirtualMachineByName(virtualMachineName);

                if (virtualMachine == null) {
                    virtualMachine = new VirtualMachine();
                    virtualMachine.setName(virtualMachineName);
                    virtualMachine.setPhysicalMachine(machine);

                    dao.save(virtualMachine);

                    this.subscriptionsCount++;
                    logger.info("Subscription migrated: {}", virtualMachineName);
                }

                wrapper.deleteSubscription(id);
            }
        }
    }

    public void migrateNonPersistedModelFromFile(final File file) throws IOException {
        LineIterator iterator = FileUtils.lineIterator(file);
        RedisDao dao = RedisDaoFactory.getInstance();

        try {
            while (iterator.hasNext()) {
                String line = iterator.nextLine();
                insertMachineFromCSVLine(dao, line);
            }
        } finally {
            LineIterator.closeQuietly(iterator);
        }
    }

    public void migrateNonPersistedModelFromRedis() throws UnknownHostException, IOException {
        RedisDao dao = RedisDaoFactory.getInstance();
        Jedis jedis = new Jedis(host, port);
        jedis.connect();

        jedis.select(database);

        long len = jedis.llen(MachineListKey);

        for (int i = 0; i < len; i++) {
            insertMachineFromCSVLine(dao, jedis.lindex(MachineListKey, i));
        }

        jedis.del(MachineListKey);

        jedis.disconnect();
    }

    private void insertMachineFromCSVLine(final RedisDao dao, final String csvLine) {
        String[] fields = csvLine.split(",");

        if (fields.length == 5) {
            String ip = fields[0];
            String port = fields[1];
            String user = fields[2];
            String pass = fields[3];
            String type = fields[4];

            insertMachine(dao, String.format("http://%s:%s/", ip, port), type, user, pass);
        }
    }

    private PhysicalMachine insertMachine(final RedisDao dao, final String address, final String type,
            final String username, final String password) {
        PhysicalMachine machine = dao.findPhysicalMachineByAddress(address);

        if (machine == null) {
            try {
                URL url = new URL(address);

                String finalType = type;

                if (this.hypervisors.containsKey(type)) {
                    finalType = this.hypervisors.get(type).name();
                }

                String finalURL = String.format("http://%s:%s/", url.getHost(), this.ports.get(finalType));

                machine = dao.findPhysicalMachineByAddress(finalURL);

                if (machine == null) {
                    VirtualMachinesCache cache = new VirtualMachinesCache();
                    dao.save(cache);

                    machine = new PhysicalMachine();

                    machine.setAddress(finalURL);
                    machine.setType(finalType);
                    machine.setUsername(username);
                    machine.setPassword(password);
                    machine.setVirtualMachines(cache);

                    dao.save(machine);

                    this.machinesCount++;
                    logger.info("Physical machine migrated: {} {}", machine.getAddress(), machine.getType());
                }
            } catch (MalformedURLException e) {
                logger.error("Invalid physical machine address {}", address);
                return null;
            }

        }

        return machine;
    }

    public int getMachinesCount() {
        return machinesCount;
    }

    public int getSubscriptionsCount() {
        return subscriptionsCount;
    }

    private static Options buildOptions() {
        Options options = new Options();
        options.addOption("help", "help", false, "Print this usage information.");
        options.addOption("f", "file", true, "CSV file with the machines to migrate.");
        options.addOption("h", "host", true, "Redis host.");
        options.addOption("p", "port", true, "Redis port.");

        return options;
    }

    private static void printUsage() {
        HelpFormatter formatter = new HelpFormatter();

        formatter.printHelp("java -jar lib/vsm-migration.jar", buildOptions(), true);
    }

    public static void main(String[] args) throws UnknownHostException, IOException {
        String host = getProperty("abiquo.redis.host", "localhost");
        int port = Integer.valueOf(getProperty("abiquo.redis.port", "6379"));

        CommandLine command = null;
        String filename = null;

        try {
            // Parse the command line arguments
            command = new PosixParser().parse(buildOptions(), args);

            if (command.hasOption("help")) {
                printUsage();
                System.exit(0);
            }

            if (command.hasOption("f")) {
                filename = command.getOptionValue("f");
            }

            if (command.hasOption("h")) {
                host = command.getOptionValue("h");
            }

            if (command.hasOption("p")) {
                port = Integer.parseInt(command.getOptionValue("p"));
            }
        } catch (Exception e) {
            logger.error("Error while parsing arguments. " + e.getMessage());
            printUsage();
            System.exit(-1);
        }

        // Start migration
        Migrator migrator = new Migrator(host, port, 0);
        logger.info("Migrating from 1.6.8 to 1.7 data model on redis located at {}:{}", host, port);

        if (filename == null) {
            migrator.migrateNonPersistedModelFromRedis();
        } else {
            File file = new File(filename);
            migrator.migrateNonPersistedModelFromFile(file);
        }

        migrator.migratePersistedModel();

        logger.info("Number of migrated physical machines: {}", migrator.getMachinesCount());
        logger.info("Number of migrated subscriptions: {}", migrator.getSubscriptionsCount());

        System.exit(0);
    }

    private static String getProperty(String name, String defaultValue) {
        String value = System.getProperty(name);
        return value == null ? defaultValue : value;
    }
}