| /* |
| * Copyright 2018-present Open Networking Foundation |
| |
| * Licensed 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 core |
| |
| import ( |
| "bytes" |
| "context" |
| "fmt" |
| "os/exec" |
| "strconv" |
| "time" |
| |
| "gerrit.opencord.org/voltha-bbsim/common/logger" |
| "gerrit.opencord.org/voltha-bbsim/device" |
| ) |
| |
| // TestManager is the structure for test manager |
| type TestManager struct { |
| DhcpServerIP string |
| Pid []int |
| testers map[string]map[device.Devkey]*Tester |
| ctx context.Context |
| cancel context.CancelFunc |
| } |
| |
| // Tester is the structure for Test |
| type Tester struct { |
| Type string |
| Key device.Devkey |
| Testfunc func(device.Devkey) error |
| Waitsec int |
| ctx context.Context |
| cancel context.CancelFunc |
| } |
| |
| // NewTestManager returns new TestManager |
| func NewTestManager(opt *option) *TestManager { |
| t := new(TestManager) |
| t.DhcpServerIP = opt.dhcpservip |
| return t |
| } |
| |
| // CreateTester creates instance of Tester |
| func (*TestManager) CreateTester(testtype string, opt *option, key device.Devkey, fn func(device.Devkey) error, waitsec int) *Tester { |
| logger.Debug("CreateTester() called") |
| t := new(Tester) |
| t.Type = testtype |
| t.Key = key |
| t.Testfunc = fn |
| t.Waitsec = waitsec |
| return t |
| } |
| |
| // Start does starting action - Blocking Call |
| func (tm *TestManager) Start() error { |
| ctx, cancel := context.WithCancel(context.Background()) |
| tm.ctx = ctx |
| tm.cancel = cancel |
| tm.testers = make(map[string]map[device.Devkey]*Tester) |
| tm.testers["AAA"] = map[device.Devkey]*Tester{} |
| tm.testers["DHCP"] = map[device.Devkey]*Tester{} |
| logger.Info("TestManager start") |
| return nil |
| } |
| |
| // Stop does stopping action |
| func (tm *TestManager) Stop() error { |
| if tm.cancel != nil { |
| tm.cancel() |
| } |
| tm.Initialize() |
| logger.Debug("TestManager Done") |
| return nil |
| } |
| |
| func (tm *TestManager) StartTester(t *Tester) error { |
| testtype := t.Type |
| key := t.Key |
| waitsec := t.Waitsec |
| |
| logger.Debug("StartTester type:%s called with key:%v", testtype, key) |
| child, cancel := context.WithCancel(tm.ctx) |
| t.ctx = child |
| t.cancel = cancel |
| go func() error { |
| tick := time.NewTicker(time.Second) |
| counter := 0 |
| defer func() { |
| tick.Stop() |
| logger.Debug("Tester type:%s with key %v Done", testtype, key) |
| }() |
| |
| L: |
| for counter < waitsec { |
| select { |
| case <-tick.C: |
| counter++ |
| if counter == waitsec { // TODO: This should be fixed |
| break L |
| } |
| case <-child.Done(): |
| return nil |
| } |
| } |
| err := t.Testfunc(key) |
| if err != nil { |
| return err |
| } |
| return nil |
| }() |
| |
| tm.testers[testtype][key] = t |
| return nil |
| } |
| |
| // StopTester stops the test |
| func (tm *TestManager) StopTester(testtype string, key device.Devkey) error { |
| ts := tm.testers[testtype][key] |
| ts.cancel() |
| delete(tm.testers[testtype], key) |
| return nil |
| } |
| |
| // Initialize test manager |
| func (tm *TestManager) Initialize() { |
| logger.Info("TestManager Initialize () called") |
| pids := tm.Pid |
| logger.Debug("Runnig Process: %v", pids) |
| KillProcesses(pids) |
| exec.Command("rm", "/var/run/dhcpd.pid").Run() // This is for DHCP server activation |
| exec.Command("touch", "/var/run/dhcpd.pid").Run() // This is for DHCP server activation |
| } |
| |
| // KillProcesses kill process by specified pid |
| func KillProcesses(pids []int) error { |
| for _, pname := range pids { |
| killProcess(pname) |
| } |
| return nil |
| } |
| |
| func killProcess(pid int) error { |
| err := exec.Command("kill", strconv.Itoa(pid)).Run() |
| if err != nil { |
| logger.Error("Fail to kill %d: %v", pid, err) |
| return err |
| } |
| logger.Info("Successfully killed %d", pid) |
| return nil |
| } |
| |
| func activateWPASupplicant(key device.Devkey) (err error) { |
| if err = startEAPClient(key.Intfid, key.ID); err != nil { |
| errmsg := fmt.Sprintf("Failed to activate WPA Supplicant intfid: %d onuid: %d", key.Intfid, key.ID) |
| logger.Error(errmsg) |
| } |
| logger.Info("Successfuly activateWPASupplicant() for intfid:%d onuid:%d", key.Intfid, key.ID) |
| return nil |
| } |
| |
| func activateDHCPClient(key device.Devkey) (err error) { |
| if err = startDHCPClient(key.Intfid, key.ID); err != nil { |
| errmsg := fmt.Sprintf("Failed to activate DHCP client intfid: %d onuid: %d", key.Intfid, key.ID) |
| logger.Error(errmsg) |
| } |
| return nil |
| } |
| |
| func activateDHCPServer(veth string, serverip string) error { |
| err := exec.Command("ip", "addr", "add", serverip, "dev", veth).Run() |
| if err != nil { |
| logger.Error("Fail to add ip to %s address: %s", veth, err) |
| return err |
| } |
| err = exec.Command("ip", "link", "set", veth, "up").Run() |
| if err != nil { |
| logger.Error("Fail to set %s up: %s", veth, err) |
| return err |
| } |
| dhcp := "/usr/local/bin/dhcpd" |
| conf := "/etc/dhcp/dhcpd.conf" |
| logfile := "/tmp/dhcplog" |
| var stderr bytes.Buffer |
| cmd := exec.Command(dhcp, "-cf", conf, veth, "-tf", logfile) |
| cmd.Stderr = &stderr |
| err = cmd.Run() |
| if err != nil { |
| logger.Error("Fail to activateDHCP Server (): %s, %s", err, stderr.String()) |
| return err |
| } |
| logger.Info("DHCP Server is successfully activated !") |
| return err |
| } |