f-33: net: add multi net in dispatch et vms #33
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
1ec1d44c1a
commit
0237acba81
15 changed files with 753 additions and 146 deletions
|
|
@ -19,10 +19,15 @@ type VMDisk struct {
|
|||
Dev string
|
||||
}
|
||||
|
||||
type VMNIC struct {
|
||||
Subnet string
|
||||
IP string
|
||||
Primary bool
|
||||
}
|
||||
|
||||
type StartVMCommand struct {
|
||||
Name string
|
||||
Subnet string
|
||||
IP string
|
||||
NICs []VMNIC
|
||||
Disks []VMDisk
|
||||
Memory int
|
||||
CPUs int
|
||||
|
|
@ -38,20 +43,28 @@ func (c StartVMCommand) Prepare(db *badger.DB, _ *configuration.Config) error {
|
|||
if _, err := kv.GetFromDB(db, "vm/"+c.Name+"/state"); err == nil {
|
||||
return fmt.Errorf("vm %q already exists", c.Name)
|
||||
}
|
||||
subnetState, err := state.Get(db, "subnet/"+c.Subnet)
|
||||
if err != nil {
|
||||
return fmt.Errorf("subnet %q not found", c.Subnet)
|
||||
}
|
||||
if subnetState != state.Creating && subnetState != state.Running {
|
||||
return fmt.Errorf("subnet %q is %s", c.Subnet, subnetState)
|
||||
if err := c.validateNICs(db); err != nil {
|
||||
return err
|
||||
}
|
||||
port, err := allocateMetadataPort(db)
|
||||
if err != nil {
|
||||
return fmt.Errorf("allocate metadata port: %w", err)
|
||||
}
|
||||
state.Set(db, c.Key(), state.Creating)
|
||||
kv.AddInDB(db, "vm/"+c.Name+"/subnet", c.Subnet)
|
||||
kv.AddInDB(db, "vm/"+c.Name+"/ip", c.IP)
|
||||
for i, n := range c.NICs {
|
||||
prefix := fmt.Sprintf("vm/%s/nic/%d/", c.Name, i)
|
||||
if err := kv.AddInDB(db, prefix+"subnet", n.Subnet); err != nil {
|
||||
return fmt.Errorf("store nic %d subnet: %w", i, err)
|
||||
}
|
||||
if err := kv.AddInDB(db, prefix+"ip", n.IP); err != nil {
|
||||
return fmt.Errorf("store nic %d ip: %w", i, err)
|
||||
}
|
||||
if n.Primary {
|
||||
if err := kv.AddInDB(db, prefix+"primary", "true"); err != nil {
|
||||
return fmt.Errorf("store nic %d primary: %w", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
kv.AddInDB(db, "vm/"+c.Name+"/metadata_port", strconv.Itoa(port))
|
||||
for _, d := range c.Disks {
|
||||
kv.AddInDB(db, "vm/"+c.Name+"/disk/"+d.Dev, d.Path)
|
||||
|
|
@ -75,6 +88,31 @@ func (c StartVMCommand) Prepare(db *badger.DB, _ *configuration.Config) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// validateNICs vérifie qu'il y a exactement une interface primaire et que
|
||||
// chaque subnet référencé est utilisable.
|
||||
func (c StartVMCommand) validateNICs(db *badger.DB) error {
|
||||
if len(c.NICs) == 0 {
|
||||
return fmt.Errorf("vm %q has no interface", c.Name)
|
||||
}
|
||||
primaries := 0
|
||||
for _, n := range c.NICs {
|
||||
if n.Primary {
|
||||
primaries++
|
||||
}
|
||||
subnetState, err := state.Get(db, "subnet/"+n.Subnet)
|
||||
if err != nil {
|
||||
return fmt.Errorf("subnet %q not found", n.Subnet)
|
||||
}
|
||||
if subnetState != state.Creating && subnetState != state.Running {
|
||||
return fmt.Errorf("subnet %q is %s", n.Subnet, subnetState)
|
||||
}
|
||||
}
|
||||
if primaries != 1 {
|
||||
return fmt.Errorf("vm %q has %d primary interfaces, expected exactly one", c.Name, primaries)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func allocateMetadataPort(db *badger.DB) (int, error) {
|
||||
entries, err := kv.ListByPrefix(db, "vm/")
|
||||
if err != nil {
|
||||
|
|
@ -99,21 +137,23 @@ func allocateMetadataPort(db *badger.DB) (int, error) {
|
|||
|
||||
func (c StartVMCommand) Execute(db *badger.DB, cfg *configuration.Config) error {
|
||||
timeout := time.After(time.Duration(cfg.Dispatcher.TimeoutSeconds) * time.Second)
|
||||
for {
|
||||
subnetState, err := state.Get(db, "subnet/"+c.Subnet)
|
||||
if err != nil {
|
||||
return fmt.Errorf("subnet %q not found while waiting", c.Subnet)
|
||||
}
|
||||
if subnetState == state.Running {
|
||||
break
|
||||
}
|
||||
if subnetState != state.Creating {
|
||||
return fmt.Errorf("subnet %q is %s, cannot start vm %q", c.Subnet, subnetState, c.Name)
|
||||
}
|
||||
select {
|
||||
case <-timeout:
|
||||
return fmt.Errorf("timed out waiting for subnet %q to be running", c.Subnet)
|
||||
case <-time.After(time.Duration(cfg.Dispatcher.PollSeconds) * time.Second):
|
||||
for _, n := range c.NICs {
|
||||
for {
|
||||
subnetState, err := state.Get(db, "subnet/"+n.Subnet)
|
||||
if err != nil {
|
||||
return fmt.Errorf("subnet %q not found while waiting", n.Subnet)
|
||||
}
|
||||
if subnetState == state.Running {
|
||||
break
|
||||
}
|
||||
if subnetState != state.Creating {
|
||||
return fmt.Errorf("subnet %q is %s, cannot start vm %q", n.Subnet, subnetState, c.Name)
|
||||
}
|
||||
select {
|
||||
case <-timeout:
|
||||
return fmt.Errorf("timed out waiting for subnet %q to be running", n.Subnet)
|
||||
case <-time.After(time.Duration(cfg.Dispatcher.PollSeconds) * time.Second):
|
||||
}
|
||||
}
|
||||
}
|
||||
return vm.StartVM(db, c.Name, cfg)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue