You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by se...@apache.org on 2015/07/12 22:39:09 UTC

incubator-ignite git commit: # IGNITE-1121 Implementation of control-center-agent.

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-1121 [created] dedec5ed1


# IGNITE-1121 Implementation of control-center-agent.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/dedec5ed
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/dedec5ed
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/dedec5ed

Branch: refs/heads/ignite-1121
Commit: dedec5ed1a44d8c0f092cd199eed8d4ef0429f67
Parents: d660f93
Author: sevdokimov <se...@jetbrains.com>
Authored: Sun Jul 12 23:39:01 2015 +0300
Committer: sevdokimov <se...@jetbrains.com>
Committed: Sun Jul 12 23:39:01 2015 +0300

----------------------------------------------------------------------
 modules/control-center-agent/pom.xml            |  59 ++++++++++
 .../java/org/apache/ignite/agent/Agent.java     | 108 ++++++++++++++++++
 .../apache/ignite/agent/AgentConfiguration.java |  72 ++++++++++++
 .../org/apache/ignite/agent/AgentLauncher.java  |  62 +++++++++++
 .../ignite/agent/messages/AbstractMessage.java  |  23 ++++
 .../ignite/agent/messages/AuthMessage.java      |  71 ++++++++++++
 .../ignite/agent/messages/AuthResult.java       |  55 ++++++++++
 .../ignite/agent/messages/MessageFactory.java   |  74 +++++++++++++
 modules/web-control-center/nodejs/app.js        |   3 +
 .../web-control-center/nodejs/bridge/bridge.js  | 109 +++++++++++++++++++
 modules/web-control-center/nodejs/package.json  |   3 +-
 11 files changed, 638 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/control-center-agent/pom.xml
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/pom.xml b/modules/control-center-agent/pom.xml
new file mode 100644
index 0000000..7d74127
--- /dev/null
+++ b/modules/control-center-agent/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<!--
+    POM file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ignite</groupId>
+        <artifactId>ignite-parent</artifactId>
+        <version>1</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>control-center-agent</artifactId>
+    <version>1.2.1-SNAPSHOT</version>
+
+    <properties>
+        <jetty.version>9.2.12.v20150709</jetty.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty.websocket</groupId>
+            <artifactId>websocket-client</artifactId>
+            <version>${jetty.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.3</version>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/control-center-agent/src/main/java/org/apache/ignite/agent/Agent.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/Agent.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/Agent.java
new file mode 100644
index 0000000..c3ac311
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/Agent.java
@@ -0,0 +1,108 @@
+package org.apache.ignite.agent;/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.ignite.agent.messages.*;
+import org.eclipse.jetty.websocket.api.*;
+import org.eclipse.jetty.websocket.api.annotations.*;
+
+import java.util.concurrent.*;
+
+/**
+ *
+ */
+@WebSocket
+public class Agent {
+    /** */
+    private final CountDownLatch closeLatch = new CountDownLatch(1);
+
+    /** */
+    private final AgentConfiguration cfg;
+
+    /**
+     * @param cfg Config.
+     */
+    public Agent(AgentConfiguration cfg) {
+        this.cfg = cfg;
+    }
+
+    /**
+     * @param statusCode Status code.
+     * @param reason Reason.
+     */
+    @OnWebSocketClose
+    public void onClose(int statusCode, String reason) {
+        System.out.printf("Connection closed: %d - %s%n", statusCode, reason);
+
+        closeLatch.countDown();
+    }
+
+    /**
+     * @param ses Session.
+     */
+    @OnWebSocketConnect
+    public void onConnect(Session ses) {
+        System.out.println("Authentication...");
+
+        AuthMessage authMsg = new AuthMessage(cfg.getLogin(), cfg.getPassword());
+
+        try {
+            ses.getRemote().sendString(MessageFactory.toString(authMsg));
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+    }
+
+    /**
+     * @param ses Session.
+     * @param error Error.
+     */
+    @OnWebSocketError
+    public void onError(Session ses, Throwable error) {
+        System.out.printf("Error: " + ses);
+
+        error.printStackTrace();
+
+        closeLatch.countDown();
+    }
+
+    /**
+     * @param msg Message.
+     */
+    @OnWebSocketMessage
+    public void onMessage(Session ses, String msg) {
+        AbstractMessage m = MessageFactory.fromString(msg);
+
+        if (m instanceof AuthResult) {
+            if (((AuthResult)m).isSuccess())
+                System.out.println("Authentication success");
+            else {
+                System.out.println("Authentication failed: " + ((AuthResult)m).getMessage());
+
+                ses.close();
+            }
+        }
+        else
+            System.err.printf("Unknown message: %s%n", msg);
+    }
+
+    /**
+     *
+     */
+    public void waitForClose() throws InterruptedException {
+        closeLatch.await();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/control-center-agent/src/main/java/org/apache/ignite/agent/AgentConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/AgentConfiguration.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/AgentConfiguration.java
new file mode 100644
index 0000000..7266b6f
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/AgentConfiguration.java
@@ -0,0 +1,72 @@
+package org.apache.ignite.agent;/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *
+ */
+public class AgentConfiguration {
+    /** */
+    private String login;
+
+    /** */
+    private String pwd;
+
+    /** */
+    private String uri;
+
+    /**
+     *
+     */
+    public String getLogin() {
+        return login;
+    }
+
+    /**
+     * @param login Login.
+     */
+    public void setLogin(String login) {
+        this.login = login;
+    }
+
+    /**
+     *
+     */
+    public String getPassword() {
+        return pwd;
+    }
+
+    /**
+     * @param pwd Password.
+     */
+    public void setPassword(String pwd) {
+        this.pwd = pwd;
+    }
+
+    /**
+     *
+     */
+    public String getUri() {
+        return uri;
+    }
+
+    /**
+     * @param uri Uri.
+     */
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/control-center-agent/src/main/java/org/apache/ignite/agent/AgentLauncher.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/AgentLauncher.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/AgentLauncher.java
new file mode 100644
index 0000000..360de24
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/AgentLauncher.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.agent;
+
+import org.eclipse.jetty.websocket.client.*;
+
+import java.net.*;
+
+/**
+ *
+ */
+public class AgentLauncher {
+    /**
+     * @param args Args.
+     */
+    public static void main(String[] args) throws Exception {
+        String login = args[0];
+        String pwd = args[1];
+
+        AgentConfiguration cfg = new AgentConfiguration();
+
+        cfg.setLogin(login);
+        cfg.setPassword(pwd);
+
+        if (args.length > 2)
+            cfg.setUri("ws://localhost:8088");
+        else
+            cfg.setUri(args[2]);
+
+        WebSocketClient client = new WebSocketClient();
+
+        Agent agent = new Agent(cfg);
+
+        client.start();
+
+        try {
+            client.connect(agent, new URI(cfg.getUri()));
+
+            System.out.printf("Connecting to : %s%n", cfg.getUri());
+
+            agent.waitForClose();
+        }
+        finally {
+            client.stop();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AbstractMessage.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AbstractMessage.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AbstractMessage.java
new file mode 100644
index 0000000..ec9acc7
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AbstractMessage.java
@@ -0,0 +1,23 @@
+package org.apache.ignite.agent.messages;/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *
+ */
+public abstract class AbstractMessage {
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AuthMessage.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AuthMessage.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AuthMessage.java
new file mode 100644
index 0000000..336107f
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AuthMessage.java
@@ -0,0 +1,71 @@
+package org.apache.ignite.agent.messages;/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *
+ */
+public class AuthMessage extends AbstractMessage {
+    /** */
+    private String login;
+
+    /** */
+    private String password;
+
+    /**
+     * Default constructor.
+     */
+    public AuthMessage() {
+        // No-op.
+    }
+
+    /**
+     * @param login Login.
+     * @param password Password.
+     */
+    public AuthMessage(String login, String password) {
+        this.login = login;
+        this.password = password;
+    }
+
+    /**
+     *
+     */
+    public String getLogin() {
+        return login;
+    }
+
+    /**
+     * @param login Login.
+     */
+    public void setLogin(String login) {
+        this.login = login;
+    }
+
+    /**
+     *
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * @param pwd Password.
+     */
+    public void setPassword(String pwd) {
+        this.password = pwd;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AuthResult.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AuthResult.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AuthResult.java
new file mode 100644
index 0000000..f183328
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/AuthResult.java
@@ -0,0 +1,55 @@
+package org.apache.ignite.agent.messages;/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ *
+ */
+public class AuthResult extends AbstractMessage {
+    /** */
+    private boolean success;
+
+    /** */
+    private String message;
+
+    /**
+     *
+     */
+    public boolean isSuccess() {
+        return success;
+    }
+
+    /**
+     * @param success Success.
+     */
+    public void setSuccess(boolean success) {
+        this.success = success;
+    }
+
+    /**
+     *
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * @param message Message.
+     */
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/MessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/MessageFactory.java b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/MessageFactory.java
new file mode 100644
index 0000000..c93fff1
--- /dev/null
+++ b/modules/control-center-agent/src/main/java/org/apache/ignite/agent/messages/MessageFactory.java
@@ -0,0 +1,74 @@
+package org.apache.ignite.agent.messages;/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.google.gson.*;
+
+/**
+ *
+ */
+public class MessageFactory {
+    /** */
+    private static final Gson gson = new Gson();
+
+    /** */
+    private static final JsonParser parser = new JsonParser();
+
+    /**
+     * Default constructor.
+     */
+    private MessageFactory() {
+        // No-op.
+    }
+
+    /**
+     * @param msg Message.
+     */
+    public static String toString(AbstractMessage msg) {
+        assert msg.getClass().getPackage().equals(MessageFactory.class.getPackage());
+
+        JsonObject json = (JsonObject)gson.toJsonTree(msg);
+
+        json.addProperty("type", msg.getClass().getSimpleName());
+
+        return gson.toJson(json);
+    }
+
+    /**
+     * @param jsonStr Json string.
+     */
+    public static AbstractMessage fromString(String jsonStr) {
+        JsonElement jsonElement = parser.parse(jsonStr);
+
+        if (!(jsonElement instanceof JsonObject))
+            throw new IllegalArgumentException();
+
+        JsonObject json = (JsonObject)jsonElement;
+
+        String type = json.getAsJsonPrimitive("type").getAsString();
+
+        Class<? extends AbstractMessage> cls;
+
+        try {
+            cls = (Class<? extends AbstractMessage>)Class.forName(MessageFactory.class.getPackage().getName() + '.' + type);
+        }
+        catch (ClassNotFoundException e) {
+            throw new IllegalArgumentException(e);
+        }
+
+        return gson.fromJson(json, cls);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/web-control-center/nodejs/app.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/app.js b/modules/web-control-center/nodejs/app.js
index 79e51c7..8d05810 100644
--- a/modules/web-control-center/nodejs/app.js
+++ b/modules/web-control-center/nodejs/app.js
@@ -34,6 +34,7 @@ var summary = require('./routes/summary');
 var adminRouter = require('./routes/admin');
 var profileRouter = require('./routes/profile');
 var sqlRouter = require('./routes/sql');
+var bridge = require('./bridge/bridge');
 
 var uiUtils = require('./helpers/ui-utils');
 
@@ -166,4 +167,6 @@ app.use(function (err, req, res) {
     });
 });
 
+bridge.startServer();
+
 module.exports = app;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/web-control-center/nodejs/bridge/bridge.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/bridge/bridge.js b/modules/web-control-center/nodejs/bridge/bridge.js
new file mode 100644
index 0000000..74c6ae5
--- /dev/null
+++ b/modules/web-control-center/nodejs/bridge/bridge.js
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var WebSocketServer = require('ws').Server;
+
+var http = require('http');
+
+var db = require('../db');
+
+var srv;
+
+var clients = {};
+
+function Client(ws) {
+    var self = this;
+
+    this.ws = ws;
+
+    ws.on('close', function() {
+        if (self.userId) {
+            var connections = clients[self.userId];
+
+            if (connections) {
+                removeFromArray(connections, self);
+            }
+        }
+    });
+
+    ws.on('message', function (msg) {
+        var m = JSON.parse(msg);
+
+        switch (m.type) {
+            case 'AuthMessage':
+                var account = db.Account.findByUsername(m.login, function(err, account) {
+                    if (err) {
+                        ws.send("{type: 'AuthResult', success: false}");
+                    }
+                    else {
+                        account.authenticate(m.password, function(err, user, res) {
+                            if (!user) {
+                                ws.send(JSON.stringify({type: 'AuthResult', success: false, message: res.message}));
+                            }
+                            else {
+                                ws.send("{type: 'AuthResult', success: true}");
+
+                                self.userId = account._id;
+
+                                var existingConnections = clients[account._id];
+
+                                if (!existingConnections) {
+                                    existingConnections = [];
+
+                                    clients[account._id] = existingConnections;
+                                }
+
+                                existingConnections.push(self);
+                            }
+                        });
+                    }
+                });
+
+                break;
+
+            default:
+                ws.close()
+        }
+    });
+}
+
+function Server() {
+    var server = http.createServer();
+    server.listen(8088);
+
+    var wss = new WebSocketServer({ server: server });
+
+    wss.on('connection', function(ws) {
+        var client = new Client(ws);
+    })
+}
+
+function removeFromArray(arr, val) {
+    var idx;
+
+    while ((idx = arr.indexOf(val)) !== -1) {
+        arr.splice(idx, 1);
+    }
+}
+
+exports.startServer = function() {
+    srv = new Server();
+};
+
+exports.findClient = function(userId) {
+    return clients[userId];
+};

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dedec5ed/modules/web-control-center/nodejs/package.json
----------------------------------------------------------------------
diff --git a/modules/web-control-center/nodejs/package.json b/modules/web-control-center/nodejs/package.json
index 82a3906..696d31a 100644
--- a/modules/web-control-center/nodejs/package.json
+++ b/modules/web-control-center/nodejs/package.json
@@ -27,7 +27,8 @@
     "passport-local-mongoose": "^1.0.0",
     "pg": "^4.4.0",
     "serve-favicon": "~2.2.0",
-    "util": "^0.10.3"
+    "util": "^0.10.3",
+    "ws": "~0.7.2"
   },
   "devDependencies": {
     "morgan": "~1.5.1",