Joe Topjian | 99a0613 | 2015-02-22 05:06:25 +0000 | [diff] [blame] | 1 | package networks |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "time" |
| 6 | |
| 7 | "github.com/mitchellh/mapstructure" |
| 8 | "github.com/rackspace/gophercloud" |
| 9 | "github.com/rackspace/gophercloud/pagination" |
| 10 | ) |
| 11 | |
| 12 | // A Network represents a nova-network that an instance communicates on |
| 13 | type Network struct { |
| 14 | // The Bridge that VIFs on this network are connected to |
| 15 | Bridge string `mapstructure:"bridge"` |
| 16 | |
| 17 | // BridgeInterface is what interface is connected to the Bridge |
| 18 | BridgeInterface string `mapstructure:"bridge_interface"` |
| 19 | |
| 20 | // The Broadcast address of the network. |
| 21 | Broadcast string `mapstructure:"broadcast"` |
| 22 | |
| 23 | // CIDR is the IPv4 subnet. |
| 24 | CIDR string `mapstructure:"cidr"` |
| 25 | |
| 26 | // CIDRv6 is the IPv6 subnet. |
| 27 | CIDRv6 string `mapstructure:"cidr_v6"` |
| 28 | |
| 29 | // CreatedAt is when the network was created.. |
| 30 | CreatedAt time.Time `mapstructure:"-"` |
| 31 | |
| 32 | // Deleted shows if the network has been deleted. |
| 33 | Deleted bool `mapstructure:"deleted"` |
| 34 | |
| 35 | // DeletedAt is the time when the network was deleted. |
| 36 | DeletedAt time.Time `mapstructure:"-"` |
| 37 | |
| 38 | // DHCPStart is the start of the DHCP address range. |
| 39 | DHCPStart string `mapstructure:"dhcp_start"` |
| 40 | |
| 41 | // DNS1 is the first DNS server to use through DHCP. |
| 42 | DNS1 string `mapstructure:"dns_1"` |
| 43 | |
| 44 | // DNS2 is the first DNS server to use through DHCP. |
| 45 | DNS2 string `mapstructure:"dns_2"` |
| 46 | |
| 47 | // Gateway is the network gateway. |
| 48 | Gateway string `mapstructure:"gateway"` |
| 49 | |
| 50 | // Gatewayv6 is the IPv6 network gateway. |
| 51 | Gatewayv6 string `mapstructure:"gateway_v6"` |
| 52 | |
| 53 | // Host is the host that the network service is running on. |
| 54 | Host string `mapstructure:"host"` |
| 55 | |
| 56 | // ID is the UUID of the network. |
| 57 | ID string `mapstructure:"id"` |
| 58 | |
| 59 | // Injected determines if network information is injected into the host. |
| 60 | Injected bool `mapstructure:"injected"` |
| 61 | |
| 62 | // Label is the common name that the network has.. |
| 63 | Label string `mapstructure:"label"` |
| 64 | |
| 65 | // MultiHost is if multi-host networking is enablec.. |
| 66 | MultiHost bool `mapstructure:"multi_host"` |
| 67 | |
| 68 | // Netmask is the network netmask. |
| 69 | Netmask string `mapstructure:"netmask"` |
| 70 | |
| 71 | // Netmaskv6 is the IPv6 netmask. |
| 72 | Netmaskv6 string `mapstructure:"netmask_v6"` |
| 73 | |
| 74 | // Priority is the network interface priority. |
| 75 | Priority int `mapstructure:"priority"` |
| 76 | |
| 77 | // ProjectID is the project associated with this network. |
| 78 | ProjectID string `mapstructure:"project_id"` |
| 79 | |
| 80 | // RXTXBase configures bandwidth entitlement. |
| 81 | RXTXBase int `mapstructure:"rxtx_base"` |
| 82 | |
| 83 | // UpdatedAt is the time when the network was last updated. |
| 84 | UpdatedAt time.Time `mapstructure:"-"` |
| 85 | |
| 86 | // VLAN is the vlan this network runs on. |
| 87 | VLAN int `mapstructure:"vlan"` |
| 88 | |
| 89 | // VPNPrivateAddress is the private address of the CloudPipe VPN. |
| 90 | VPNPrivateAddress string `mapstructure:"vpn_private_address"` |
| 91 | |
| 92 | // VPNPublicAddress is the public address of the CloudPipe VPN. |
| 93 | VPNPublicAddress string `mapstructure:"vpn_public_address"` |
| 94 | |
| 95 | // VPNPublicPort is the port of the CloudPipe VPN. |
| 96 | VPNPublicPort int `mapstructure:"vpn_public_port"` |
| 97 | } |
| 98 | |
| 99 | // NetworkPage stores a single, only page of Networks |
| 100 | // results from a List call. |
| 101 | type NetworkPage struct { |
| 102 | pagination.SinglePageBase |
| 103 | } |
| 104 | |
| 105 | // IsEmpty determines whether or not a NetworkPage is empty. |
| 106 | func (page NetworkPage) IsEmpty() (bool, error) { |
| 107 | va, err := ExtractNetworks(page) |
| 108 | return len(va) == 0, err |
| 109 | } |
| 110 | |
| 111 | // ExtractNetworks interprets a page of results as a slice of Networks |
| 112 | func ExtractNetworks(page pagination.Page) ([]Network, error) { |
| 113 | var res struct { |
| 114 | Networks []Network `mapstructure:"networks"` |
| 115 | } |
| 116 | |
| 117 | err := mapstructure.Decode(page.(NetworkPage).Body, &res) |
| 118 | |
| 119 | var rawNetworks []interface{} |
| 120 | body := page.(NetworkPage).Body |
| 121 | switch body.(type) { |
| 122 | case map[string]interface{}: |
| 123 | rawNetworks = body.(map[string]interface{})["networks"].([]interface{}) |
| 124 | case map[string][]interface{}: |
| 125 | rawNetworks = body.(map[string][]interface{})["networks"] |
| 126 | default: |
| 127 | return res.Networks, fmt.Errorf("Unknown type") |
| 128 | } |
| 129 | |
| 130 | for i := range rawNetworks { |
| 131 | thisNetwork := rawNetworks[i].(map[string]interface{}) |
| 132 | if t, ok := thisNetwork["created_at"].(string); ok && t != "" { |
| 133 | createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t) |
| 134 | if err != nil { |
| 135 | return res.Networks, err |
| 136 | } |
| 137 | res.Networks[i].CreatedAt = createdAt |
| 138 | } |
| 139 | |
| 140 | if t, ok := thisNetwork["updated_at"].(string); ok && t != "" { |
| 141 | updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) |
| 142 | if err != nil { |
| 143 | return res.Networks, err |
| 144 | } |
| 145 | res.Networks[i].UpdatedAt = updatedAt |
| 146 | } |
| 147 | |
| 148 | if t, ok := thisNetwork["deleted_at"].(string); ok && t != "" { |
| 149 | deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) |
| 150 | if err != nil { |
| 151 | return res.Networks, err |
| 152 | } |
| 153 | res.Networks[i].DeletedAt = deletedAt |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | return res.Networks, err |
| 158 | } |
| 159 | |
| 160 | type NetworkResult struct { |
| 161 | gophercloud.Result |
| 162 | } |
| 163 | |
| 164 | // Extract is a method that attempts to interpret any Network resource |
| 165 | // response as a Network struct. |
| 166 | func (r NetworkResult) Extract() (*Network, error) { |
| 167 | if r.Err != nil { |
| 168 | return nil, r.Err |
| 169 | } |
| 170 | |
| 171 | var res struct { |
| 172 | Network *Network `json:"network" mapstructure:"network"` |
| 173 | } |
| 174 | |
| 175 | config := &mapstructure.DecoderConfig{ |
| 176 | Result: &res, |
| 177 | WeaklyTypedInput: true, |
| 178 | } |
| 179 | decoder, err := mapstructure.NewDecoder(config) |
| 180 | if err != nil { |
| 181 | return nil, err |
| 182 | } |
| 183 | |
| 184 | if err := decoder.Decode(r.Body); err != nil { |
| 185 | return nil, err |
| 186 | } |
| 187 | |
| 188 | b := r.Body.(map[string]interface{})["network"].(map[string]interface{}) |
| 189 | |
| 190 | if t, ok := b["created_at"].(string); ok && t != "" { |
| 191 | createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t) |
| 192 | if err != nil { |
| 193 | return res.Network, err |
| 194 | } |
| 195 | res.Network.CreatedAt = createdAt |
| 196 | } |
| 197 | |
| 198 | if t, ok := b["updated_at"].(string); ok && t != "" { |
| 199 | updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) |
| 200 | if err != nil { |
| 201 | return res.Network, err |
| 202 | } |
| 203 | res.Network.UpdatedAt = updatedAt |
| 204 | } |
| 205 | |
| 206 | if t, ok := b["deleted_at"].(string); ok && t != "" { |
| 207 | deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t) |
| 208 | if err != nil { |
| 209 | return res.Network, err |
| 210 | } |
| 211 | res.Network.DeletedAt = deletedAt |
| 212 | } |
| 213 | |
| 214 | return res.Network, err |
| 215 | |
| 216 | } |
| 217 | |
| 218 | // GetResult is the response from a Get operation. Call its Extract method to interpret it |
| 219 | // as a Network. |
| 220 | type GetResult struct { |
| 221 | NetworkResult |
| 222 | } |