| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 package local | |
| 2 | |
| 3 import ( | |
| 4 "encoding/xml" | |
| 5 "io/ioutil" | |
| 6 "os" | |
| 7 "os/exec" | |
| 8 "strings" | |
| 9 "text/template" | |
| 10 ) | |
| 11 | |
| 12 // networks represents a local virtual network. | |
|
niemeyer
2012/05/24 16:31:35
s/networks/network/
| |
| 13 type network struct { | |
| 14 XMLName xml.Name `xml:"network"` | |
| 15 Name string `xml:"name"` | |
| 16 Bridge bridge `xml:"bridge"` | |
| 17 Ip ip `xml:"ip"` | |
| 18 Subnet int | |
| 19 } | |
| 20 | |
| 21 // ip represents an ip with the given address and netmask. | |
| 22 type ip struct { | |
| 23 Ip string `xml:"address,attr"` | |
| 24 Mask string `xml:"netmask,attr"` | |
| 25 } | |
| 26 | |
| 27 // bridge represents a briddge with the given name. | |
| 28 type bridge struct { | |
| 29 Name string `xml:"name,attr"` | |
| 30 } | |
| 31 | |
| 32 // newNetwork returns a started network. | |
| 33 func newNetwork(name string, subnet int) (*network, error) { | |
| 34 n := network{Name: name, Subnet: subnet} | |
| 35 err := n.start() | |
| 36 if err != nil { | |
| 37 return nil, err | |
| 38 } | |
| 39 err = n.loadAttributes() | |
| 40 if err != nil { | |
| 41 return nil, err | |
| 42 } | |
| 43 return &n, nil | |
| 44 } | |
| 45 | |
| 46 // loadAttributes loads the attributes for a network. | |
| 47 func (n *network) loadAttributes() error { | |
| 48 output, err := exec.Command("virsh", "net-dumpxml", n.Name).Output() | |
| 49 if err != nil { | |
| 50 return err | |
| 51 } | |
| 52 return xml.Unmarshal(output, &n) | |
| 53 } | |
| 54 | |
| 55 // running returns true if network name is in the | |
| 56 // list of networks and is active. | |
| 57 func (n *network) running() (bool, error) { | |
| 58 networks, err := listNetworks() | |
| 59 if err != nil { | |
| 60 return false, err | |
| 61 } | |
| 62 return networks[n.Name], nil | |
| 63 } | |
| 64 | |
| 65 // exists returns true if network name is in the | |
| 66 // list of networks. | |
| 67 func (n *network) exists() (bool, error) { | |
| 68 networks, err := listNetworks() | |
| 69 if err != nil { | |
| 70 return false, err | |
| 71 } | |
| 72 _, exists := networks[n.Name] | |
| 73 return exists, nil | |
| 74 } | |
| 75 | |
| 76 // virsh replaces %d with an auto increment | |
| 77 // number to make the bridge name unique | |
| 78 var libVirtNetworkTemplate = template.Must(template.New("").Parse(` | |
| 79 <network> | |
| 80 <name>{{.Name}}</name> | |
| 81 <bridge name='vbr-{{.Name}}-%d' /> | |
| 82 <forward/> | |
| 83 <ip address='192.168.{{.Subnet}}.1' netmask='255.255.255.0'> | |
| 84 <dhcp> | |
| 85 <range start='192.168.{{.Subnet}}.2' end='192.168.{{.Subnet}}.254' /> | |
| 86 </dhcp> | |
| 87 </ip> | |
| 88 </network> | |
| 89 `)) | |
| 90 | |
| 91 // start ensures that the network is started. | |
| 92 // If network name does not exist, it is created. | |
|
rog
2012/05/24 14:07:04
s/network/the network/
| |
| 93 func (n *network) start() error { | |
| 94 exists, err := n.exists() | |
| 95 if err != nil { | |
| 96 return err | |
| 97 } | |
| 98 if exists { | |
| 99 running, err := n.running() | |
| 100 if err != nil { | |
| 101 return err | |
| 102 } | |
| 103 if running { | |
| 104 return nil | |
| 105 } | |
| 106 return exec.Command("virsh", "net-start", n.Name).Run() | |
| 107 } | |
| 108 file, err := ioutil.TempFile(os.TempDir(), "network") | |
| 109 if err != nil { | |
| 110 return err | |
| 111 } | |
| 112 defer file.Close() | |
| 113 defer os.Remove(file.Name()) | |
| 114 err = libVirtNetworkTemplate.Execute(file, n) | |
| 115 if err != nil { | |
| 116 return err | |
| 117 } | |
| 118 err = exec.Command("virsh", "net-define", file.Name()).Run() | |
| 119 if err != nil { | |
| 120 return err | |
| 121 } | |
| 122 return exec.Command("virsh", "net-start", n.Name).Run() | |
| 123 } | |
| 124 | |
| 125 // listNetworks returns a map from network name to active status. | |
| 126 func listNetworks() (map[string]bool, error) { | |
| 127 output, err := exec.Command("virsh", "net-list", "--all").Output() | |
| 128 if err != nil { | |
| 129 return nil, err | |
| 130 } | |
| 131 // Remove the header. | |
| 132 networks := map[string]bool{} | |
| 133 lines := strings.Split(string(output), "\n") | |
| 134 if len(lines) < 3 { | |
| 135 return networks, nil | |
| 136 } | |
| 137 lines = lines[2:] | |
| 138 for _, line := range lines { | |
| 139 if line == "" { | |
| 140 continue | |
| 141 } | |
| 142 fields := strings.Fields(line) | |
| 143 if len(fields) > 2 { | |
| 144 networks[fields[0]] = fields[1] == "active" | |
| 145 } | |
| 146 } | |
| 147 return networks, nil | |
| 148 } | |
| OLD | NEW |