Skip to content

Commit

Permalink
registry server intial implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
ruizeng committed Nov 10, 2015
1 parent 2f5ec27 commit 21a5520
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 3 deletions.
15 changes: 15 additions & 0 deletions pkg/rpcs/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package rpcs

// device register args
type DeviceRegisterArgs struct {
ProductKey string
DeviceCode string
DeviceVersion string
}

// device update args
type DeviceUpdateArgs struct {
DeviceIdentifier string
DeviceName string
DeviceDescription string
}
149 changes: 148 additions & 1 deletion services/registry/registry.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package main

import (
"errors"
"flag"
"github.com/PandoCloud/pando-cloud/pkg/generator"
"github.com/PandoCloud/pando-cloud/pkg/models"
"github.com/PandoCloud/pando-cloud/pkg/rpcs"
)

const (
Expand All @@ -26,7 +28,9 @@ func NewRegistry() (*Registry, error) {
}, nil
}

func (r *Registry) CreateVendor(vendor *models.Vendor, reply *models.Vendor) error {
// SaveVendor will create a vendor if the ID field is not initialized
// if ID field is initialized, it will update the conresponding vendor.
func (r *Registry) SaveVendor(vendor *models.Vendor, reply *models.Vendor) error {
db, err := getDB()
if err != nil {
return err
Expand All @@ -53,7 +57,150 @@ func (r *Registry) CreateVendor(vendor *models.Vendor, reply *models.Vendor) err
return nil
}

// SaveProduct will create a product if the ID field is not initialized
// if ID field is initialized, it will update the conresponding product.
func (r *Registry) SaveProduct(product *models.Product, reply *models.Product) error {
db, err := getDB()
if err != nil {
return err
}

err = db.Save(product).Error
if err != nil {
return err
}

key, err := r.keygen.GenRandomKey(int64(product.ID))
if err != nil {
return err
}

product.ProductKey = key

err = db.Save(product).Error
if err != nil {
return err
}

reply = product
return nil
}

// ValidProduct try to validate the given product key.
// if success, it will reply the corresponding product
func (r *Registry) ValidateProduct(key string, reply *models.Product) error {
db, err := getDB()
if err != nil {
return err
}

id, err := r.keygen.DecodeIdFromRandomKey(key)
if err != nil {
return err
}

err = db.First(reply, id).Error
if err != nil {
return err
}

if reply.ProductKey != key {
return errors.New("product key not match.")
}

return nil
}

// RegisterDevice try to register a device to our platform.
// if the device has already been registered,
// the registration will success return the registered device before.
func (r *Registry) RegisterDevice(args *rpcs.DeviceRegisterArgs, reply *models.Device) error {
db, err := getDB()
if err != nil {
return err
}

product := &models.Product{}
err = r.ValidateProduct(args.ProductKey, product)
if err != nil {
return err
}

identifier := genDeviceIdentifier(product.VendorID, product.ID, args.DeviceCode)
if db.Where(&models.Device{DeviceIdentifier: identifier}).First(reply).RecordNotFound() {
// device is not registered yet.
reply.ProductID = product.ID
reply.DeviceIdentifier = identifier
reply.DeviceName = product.ProductName // product name as default device name.
reply.DeviceDescription = product.ProductDescription
reply.DeviceVersion = args.DeviceVersion
err = db.Save(reply).Error
if err != nil {
return err
}
// generate a random device key with hex encoding.
reply.DeviceKey, err = r.keygen.GenRandomKey(reply.ID)
if err != nil {
return err
}
// generate a random password with base64 encoding.
reply.DeviceSecret, err = generator.GenRandomPassword()
if err != nil {
return err
}

err = db.Save(reply).Error
if err != nil {
return err
}
} else {
// device has aleady been saved. just update version info.
reply.DeviceVersion = args.DeviceVersion
err = db.Save(reply).Error
if err != nil {
return err
}
}

return nil
}

// FindDeviceByIdentifier will find the device by indentifier
func (r *Registry) FindDeviceByIdentifier(identifier string, reply *models.Device) error {
db, err := getDB()
if err != nil {
return err
}

err = db.Where(&models.Device{
DeviceIdentifier: identifier,
}).First(reply).Error

if err != nil {
return err
}
return nil
}

// UpdateDevice will update a device info by identifier
func (r *Registry) UpdateDeviceInfo(args *rpcs.DeviceUpdateArgs, reply *models.Device) error {
db, err := getDB()
if err != nil {
return err
}

err = r.FindDeviceByIdentifier(args.DeviceIdentifier, reply)
if err != nil {
return err
}

reply.DeviceName = args.DeviceName
reply.DeviceDescription = args.DeviceDescription

err = db.Save(reply).Error
if err != nil {
return err
}

return nil
}
73 changes: 71 additions & 2 deletions services/registry/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"github.com/PandoCloud/pando-cloud/pkg/models"
"github.com/PandoCloud/pando-cloud/pkg/mysql"
"github.com/PandoCloud/pando-cloud/pkg/rpcs"
"testing"
)

Expand All @@ -11,14 +12,80 @@ func testVendor(t *testing.T, r *Registry) {
VendorName: "testvendor",
VendorDescription: "this is a test vendor",
}
err := r.CreateVendor(vendor, vendor)
err := r.SaveVendor(vendor, vendor)
if err != nil {
t.Fatal(err)
}
t.Log(vendor)
}

func TestVendor(t *testing.T) {
var (
testProductKey = ""
)

func testProduct(t *testing.T, r *Registry) {
product := &models.Product{
VendorID: 1,
ProductName: "test product.",
ProductDescription: "this is a test product",
ProductConfig: "{}",
}
err := r.SaveProduct(product, product)
if err != nil {
t.Fatal(err)
}
t.Log(product)

product.ProductName = "test for update."
err = r.SaveProduct(product, product)
if err != nil {
t.Fatal(err)
}
t.Log(product)

reply := &models.Product{}
err = r.ValidateProduct(product.ProductKey, reply)
if err != nil {
t.Error(err)
}
t.Log(reply)

testProductKey = product.ProductKey

err = r.ValidateProduct("this is a wrong key , you know", reply)
if err == nil {
t.Error("wrong key should fail product key validation.")
}
}

func testDevice(t *testing.T, r *Registry) {
args := &rpcs.DeviceRegisterArgs{
ProductKey: testProductKey,
DeviceCode: "ffffaaeeccbb",
DeviceVersion: "android-gprs-v1",
}
device := &models.Device{}
err := r.RegisterDevice(args, device)
if err != nil {
t.Fatal(err)
}
t.Log(device)

device.DeviceDescription = "test change device info."

args2 := &rpcs.DeviceUpdateArgs{
DeviceIdentifier: device.DeviceIdentifier,
DeviceName: "testupdatename",
DeviceDescription: "test change device info.",
}
err = r.UpdateDeviceInfo(args2, device)
if err != nil {
t.Error(err)
}
t.Log(device)
}

func TestRegistry(t *testing.T) {
mysql.MigrateDatabase(defaultDBHost, defaultDBPort, defaultDBName, defaultDBUser, "")

*confAESKey = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
Expand All @@ -29,4 +96,6 @@ func TestVendor(t *testing.T) {
}

testVendor(t, r)
testProduct(t, r)
testDevice(t, r)
}
9 changes: 9 additions & 0 deletions services/registry/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

import (
"strconv"
)

func genDeviceIdentifier(vendor int32, product int32, device string) string {
return strconv.FormatInt(int64(vendor), 16) + "-" + strconv.FormatInt(int64(product), 16) + "-" + device
}
13 changes: 13 additions & 0 deletions services/registry/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"testing"
)

func TestGenDeviceIdentifier(t *testing.T) {
vendorid, productid, devicecode := int32(100), int32(100), "ffaf4fffeeaa"
identifier := genDeviceIdentifier(vendorid, productid, devicecode)
if identifier != "64-64-ffaf4fffeeaa" {
t.Errorf("gen identifier error, need %s, got %s ", "64-64-ffaf4fffeeaa", identifier)
}
}

0 comments on commit 21a5520

Please sign in to comment.