-
Notifications
You must be signed in to change notification settings - Fork 29
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
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,3 +17,4 @@ site/ | |
coverage.txt | ||
releases/ | ||
gasper*.log | ||
seaweed/ |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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" | ||||||
) | ||||||
|
@@ -98,3 +99,44 @@ func setupDatabaseContainer(serviceName string) { | |||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
func setupSeaweedfsContainer(serviceName string) { | ||||||
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) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
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) | ||||||
} | ||||||
} | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -4,6 +4,7 @@ import ( | |||||
"encoding/json" | ||||||
"fmt" | ||||||
"io/ioutil" | ||||||
"os" | ||||||
"time" | ||||||
|
||||||
dockerTypes "github.com/docker/docker/api/types" | ||||||
|
@@ -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()) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: "", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
HostPort: fmt.Sprintf("%d", containerCfg.ContainerPort1)}}, | ||||||
nat.Port(containerPortRule2): []nat.PortBinding{{ | ||||||
HostIP: "", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
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() | ||||||
|
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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,6 +92,18 @@ func startAppMakerService() error { | |
} | ||
|
||
func startMasterService() error { | ||
|
||
checkAndPullImages("chrislusf/seaweedfs") | ||
err := os.MkdirAll("seaweed/seaweed-filer-storage/filerldb2", 0777) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you change Comment to distinguish |
||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly for |
||
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 | ||
|
There was a problem hiding this comment.
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