Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Network Mounted Volumes - docker based solution #224

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ site/
coverage.txt
releases/
gasper*.log
seaweed/
1 change: 1 addition & 0 deletions configs/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ type Images struct {
Mongodb string `toml:"mongodb"`
Postgresql string `toml:"postgresql"`
Redis string `toml:"redis"`
Seaweedfs string `toml:"chrislusf/seaweedfs"`
}

// Services is the configuration for all Services
Expand Down
42 changes: 42 additions & 0 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/sdslabs/gasper/lib/database"
"github.com/sdslabs/gasper/lib/docker"
"github.com/sdslabs/gasper/lib/seaweedfs"
"github.com/sdslabs/gasper/lib/utils"
"google.golang.org/grpc"
)
Expand Down Expand Up @@ -98,3 +99,44 @@ func setupDatabaseContainer(serviceName string) {
}
}
}

func setupSeaweedfsContainer(serviceName string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this function change serviceName -> seaweedType

containers, err := docker.ListContainers()
if err != nil {
utils.LogError("Main-Helper-18", err)
os.Exit(1)
}

if !utils.Contains(containers, serviceName) {
utils.LogInfo("No %s instance found in host. Building the instance.", strings.Title(serviceName))
containerID, err := seaweedfs.SetupSeaweedfsInstance(serviceName)
if err != nil {
utils.Log("There was a problem deploying %s service.", strings.Title(serviceName), utils.ErrorTAG)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
utils.Log("There was a problem deploying %s service.", strings.Title(serviceName), utils.ErrorTAG)
utils.Log("There was a problem deploying %s seaweedType", strings.Title(serviceName), utils.ErrorTAG)

utils.LogError("Main-Helper-19", err)
} else {
utils.LogInfo("%s Container has been deployed with ID:\t%s \n", strings.Title(serviceName), containerID)
}
} else {
containerStatus, err := docker.InspectContainerState(serviceName)
if err != nil {
utils.Log("Error in fetching container state. Deleting container and deploying again.", strings.Title(serviceName), utils.ErrorTAG)
utils.LogError("Main-Helper-20", err)
err := docker.DeleteContainer(serviceName)
if err != nil {
utils.LogError("Main-Helper-21", err)
}
containerID, err := seaweedfs.SetupSeaweedfsInstance(serviceName)
if err != nil {
utils.Log("There was a problem deploying %s service even after restart.", strings.Title(serviceName), utils.ErrorTAG)
utils.LogError("Main-Helper-22", err)
} else {
utils.LogInfo("Container has been deployed with ID:\t%s \n", containerID)
}
}
if !containerStatus.Running {
if err := docker.StartContainer(serviceName); err != nil {
utils.LogError("Main-Helper-23", err)
}
}
}
}
62 changes: 62 additions & 0 deletions lib/docker/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"time"

dockerTypes "github.com/docker/docker/api/types"
Expand Down Expand Up @@ -113,6 +114,67 @@ func CreateDatabaseContainer(containerCfg types.DatabaseContainer) (string, erro
return createdConf.ID, nil
}

// CreateSeaweedContainer creates a new container of the given container options, returns id of the container created
func CreateSeaweedContainer(containerCfg *types.SeaweedfsContainer) (string, error) {
ctx := context.Background()
volume := fmt.Sprintf("%s:%s", containerCfg.StoreDir, containerCfg.WorkDir)

if containerCfg.Name == types.SeaweedFiler {
err := os.MkdirAll("seaweed/seaweed-filer-storage/filerldb2", 0777)
if err != nil {
println(err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't here be return statement instead of print

}
}

envArr := []string{}
for key, value := range containerCfg.Env {
envArr = append(envArr, fmt.Sprintf("%s=%v", key, value))
}

containerPortRule1 := nat.Port(fmt.Sprintf(`%d/tcp`, containerCfg.HostPort1))
containerPortRule2 := nat.Port(fmt.Sprintf(`%d/tcp`, containerCfg.HostPort2))

containerConfig := &container.Config{
Image: containerCfg.Image,
ExposedPorts: nat.PortSet{
containerPortRule1: struct{}{},
containerPortRule2: struct{}{},
},
Env: envArr,
Volumes: map[string]struct{}{
volume: {},
},
}

containerConfig.Cmd = containerCfg.Cmd

hostConfig := &container.HostConfig{
Binds: []string{
volume,
},
PortBindings: nat.PortMap{
nat.Port(containerPortRule1): []nat.PortBinding{{
HostIP: "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
HostIP: "",
HostIP: "0.0.0.0",

HostPort: fmt.Sprintf("%d", containerCfg.ContainerPort1)}},
nat.Port(containerPortRule2): []nat.PortBinding{{
HostIP: "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
HostIP: "",
HostIP: "0.0.0.0",

HostPort: fmt.Sprintf("%d", containerCfg.ContainerPort2)}},
},
}

if containerCfg.Name != types.SeaweedMaster {
hostConfig.Links = []string{
fmt.Sprintf("%s:master", types.SeaweedMaster),
}
}

createdConf, err := cli.ContainerCreate(ctx, containerConfig, hostConfig, nil, containerCfg.Name)
if err != nil {
return "", err
}
return createdConf.ID, nil
}

// StartContainer starts the container corresponding to given containerID
func StartContainer(containerID string) error {
ctx := context.Background()
Expand Down
90 changes: 90 additions & 0 deletions lib/seaweedfs/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package seaweedfs

import (
"fmt"
"os"
"path/filepath"

"github.com/sdslabs/gasper/lib/docker"
"github.com/sdslabs/gasper/types"
)

var storepath, _ = os.Getwd()

// Maps seaweedfs's service name with its appropriate configuration
var seaweedfsMap = map[string]*types.SeaweedfsContainer{
types.SeaweedMaster: {
Image: "chrislusf/seaweedfs",
Cmd: []string{"master", "-ip=master"},
HostPort1: 9333,
ContainerPort1: 9333,
HostPort2: 19333,
ContainerPort2: 1933,
WorkDir: "/data",
StoreDir: filepath.Join(storepath, "seaweed/seaweed-master-storage"),
Name: types.SeaweedMaster,
},
types.SeaweedVolume: {
Image: "chrislusf/seaweedfs",
Cmd: []string{"volume", "-mserver=master:9333", "-port=8080"},
HostPort1: 8080,
ContainerPort1: 8080,
HostPort2: 18080,
ContainerPort2: 18080,
WorkDir: "/data",
StoreDir: filepath.Join(storepath, "seaweed/seaweed-volume-storage"),
Name: types.SeaweedVolume,
},
types.SeaweedFiler: {
Image: "chrislusf/seaweedfs",
Cmd: []string{"filer", "-master=master:9333"},
HostPort1: 8888,
ContainerPort1: 8888,
HostPort2: 18888,
ContainerPort2: 18888,
WorkDir: "/data",
StoreDir: filepath.Join(storepath, "seaweed", "seaweed-filer-storage"),
Name: types.SeaweedFiler,
},
types.SeaweedCronjob: {
Image: "chrislusf/seaweedfs",
Cmd: []string{"cronjob"},
HostPort1: 8889,
ContainerPort1: 8889,
HostPort2: 18889,
ContainerPort2: 18889,
WorkDir: "/data",
StoreDir: filepath.Join(storepath, "seaweed/seaweed-cronjob-storage"),
Env: map[string]interface{}{"CRON_SCHEDULE": "*/2 * * * * *", "WEED_MASTER": "master:9333"},
Name: types.SeaweedCronjob,
},
types.SeaweedS3: {
Image: "chrislusf/seaweedfs",
Cmd: []string{"s3", "-filer=filer:8888"},
HostPort1: 8333,
ContainerPort1: 8333,
HostPort2: 18898,
ContainerPort2: 18898,
WorkDir: "/data",
StoreDir: filepath.Join(storepath, "seaweed/seaweed-s3-storage"),
Name: types.SeaweedS3,
},
}

// SetupSeaweedfsInstance sets up containers for database
func SetupSeaweedfsInstance(seaweedType string) (string, types.ResponseError) {
if seaweedfsMap[seaweedType] == nil {
return "", types.NewResErr(500, fmt.Sprintf("Invalid seaweedfs type %s provided", seaweedType), nil)
}

containerID, err := docker.CreateSeaweedContainer(seaweedfsMap[seaweedType])
if err != nil {
return "", types.NewResErr(500, "container not created", err)
}

if err := docker.StartContainer(containerID); err != nil {
return "", types.NewResErr(500, "container not started", err)
}

return containerID, nil
}
12 changes: 12 additions & 0 deletions service_launchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ func startAppMakerService() error {
}

func startMasterService() error {

checkAndPullImages("chrislusf/seaweedfs")
err := os.MkdirAll("seaweed/seaweed-filer-storage/filerldb2", 0777)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does ldb2 signify in filerldb2 ? and Is it necessary to name it so

if err != nil {
println(err.Error())
}
setupSeaweedfsContainer(types.SeaweedMaster)
setupSeaweedfsContainer(types.SeaweedVolume)
setupSeaweedfsContainer(types.SeaweedFiler)
setupSeaweedfsContainer(types.SeaweedCronjob)
setupSeaweedfsContainer(types.SeaweedS3)

if configs.ServiceConfig.Master.MongoDB.PlugIn {
checkAndPullImages(configs.ImageConfig.Mongodb)
setupDatabaseContainer(types.MongoDBGasper)
Expand Down
15 changes: 15 additions & 0 deletions types/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,19 @@ const (

// DefaultCPUs is the default number of CPUs allotted to a container
DefaultCPUs = 0.25

//SeaweedMaster is the master service for Seaweedfs
SeaweedMaster = "seaweed_master"

//SeaweedVolume is the volume service for Seaweedfs
SeaweedVolume = "seaweed_volume"

//SeaweedFiler is the filer service for Seaweedfs
SeaweedFiler = "seaweed_filer"

//SeaweedCronjob is the cronjob service for Seaweedfs
SeaweedCronjob = "seaweed_cronjob"

//SeaweedS3 is the Seaweed service that provides support for AmazonS3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@supra08 Is support for AmazonS3 required for our use case? In future may be?

SeaweedS3 = "seaweed_s3"
)
25 changes: 25 additions & 0 deletions types/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,31 @@ type DatabaseContainer struct {
Env M
}

// SeaweedfsContainer is the configuration for creating a container
// for running the filesystem
type SeaweedfsContainer struct {
// Name of the container
Name string
// Docker image used for creating the container
Image string
// Port on which a database service is running inside the container
HostPort1 int
// Port on which a database service is running inside the container
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change Comment to distinguish HostPort1 and HostPort2

HostPort2 int
// Port of the docker container in the host system
ContainerPort1 int
// Port of the docker container in the host system
ContainerPort2 int
// Directory inside the docker container for volume mounting purposes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly for ContainerPort1 and ContainerPort2

WorkDir string
// Directory on the host system for volume mounting purposes
StoreDir string
// Custom commands to be executed on a container's startup
Cmd []string
// Environment variables
Env M
}

// HasCustomCMD checks whether a database container needs custom CMD commands on boot
func (containerCfg *DatabaseContainer) HasCustomCMD() bool {
return len(containerCfg.Cmd) > 0
Expand Down