github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/builder/cloudstack/step_configure_networking.go (about) 1 package cloudstack 2 3 import ( 4 "fmt" 5 "math/rand" 6 "strings" 7 "time" 8 9 "github.com/mitchellh/multistep" 10 "github.com/mitchellh/packer/packer" 11 "github.com/xanzy/go-cloudstack/cloudstack" 12 ) 13 14 type stepSetupNetworking struct { 15 privatePort int 16 publicPort int 17 } 18 19 func (s *stepSetupNetworking) Run(state multistep.StateBag) multistep.StepAction { 20 client := state.Get("client").(*cloudstack.CloudStackClient) 21 config := state.Get("config").(*Config) 22 ui := state.Get("ui").(packer.Ui) 23 24 ui.Say("Setup networking...") 25 26 if config.UseLocalIPAddress { 27 ui.Message("Using the local IP address...") 28 ui.Message("Networking has been setup!") 29 return multistep.ActionContinue 30 } 31 32 // Generate a random public port used to configure our port forward. 33 rand.Seed(time.Now().UnixNano()) 34 s.publicPort = 50000 + rand.Intn(10000) 35 36 // Set the currently configured port to be the private port. 37 s.privatePort = config.Comm.Port() 38 39 // Set the SSH or WinRM port to be the randomly generated public port. 40 switch config.Comm.Type { 41 case "ssh": 42 config.Comm.SSHPort = s.publicPort 43 case "winrm": 44 config.Comm.WinRMPort = s.publicPort 45 } 46 47 // Retrieve the instance ID from the previously saved state. 48 instanceID, ok := state.Get("instance_id").(string) 49 if !ok || instanceID == "" { 50 ui.Error("Could not retrieve instance_id from state!") 51 return multistep.ActionHalt 52 } 53 54 network, _, err := client.Network.GetNetworkByID( 55 config.Network, 56 cloudstack.WithProject(config.Project), 57 ) 58 if err != nil { 59 ui.Error(fmt.Sprintf("Failed to retrieve the network object: %s", err)) 60 return multistep.ActionHalt 61 } 62 63 if config.PublicIPAddress == "" { 64 ui.Message("Associating public IP address...") 65 p := client.Address.NewAssociateIpAddressParams() 66 67 if config.Project != "" { 68 p.SetProjectid(config.Project) 69 } 70 71 if network.Vpcid != "" { 72 p.SetVpcid(network.Vpcid) 73 } else { 74 p.SetNetworkid(network.Id) 75 } 76 77 // Associate a new public IP address. 78 ipAddr, err := client.Address.AssociateIpAddress(p) 79 if err != nil { 80 ui.Error(fmt.Sprintf("Failed to associate public IP address: %s", err)) 81 return multistep.ActionHalt 82 } 83 84 // Set the IP address and it's ID. 85 config.PublicIPAddress = ipAddr.Id 86 config.hostAddress = ipAddr.Ipaddress 87 88 // Store the IP address ID. 89 state.Put("ip_address_id", ipAddr.Id) 90 } 91 92 ui.Message("Creating port forward...") 93 p := client.Firewall.NewCreatePortForwardingRuleParams( 94 config.PublicIPAddress, 95 s.privatePort, 96 "TCP", 97 s.publicPort, 98 instanceID, 99 ) 100 101 // Configure the port forward. 102 p.SetNetworkid(network.Id) 103 p.SetOpenfirewall(false) 104 105 // Create the port forward. 106 forward, err := client.Firewall.CreatePortForwardingRule(p) 107 if err != nil { 108 ui.Error(fmt.Sprintf("Failed to create port forward: %s", err)) 109 } 110 111 // Store the port forward ID. 112 state.Put("port_forward_id", forward.Id) 113 114 if network.Vpcid != "" { 115 ui.Message("Creating network ACL rule...") 116 117 if network.Aclid == "" { 118 ui.Error("Failed to configure the firewall: no ACL connected to the VPC network") 119 return multistep.ActionHalt 120 } 121 122 // Create a new parameter struct. 123 p := client.NetworkACL.NewCreateNetworkACLParams("TCP") 124 125 // Configure the network ACL rule. 126 p.SetAclid(network.Aclid) 127 p.SetAction("allow") 128 p.SetCidrlist(config.CIDRList) 129 p.SetStartport(s.privatePort) 130 p.SetEndport(s.privatePort) 131 p.SetTraffictype("ingress") 132 133 // Create the network ACL rule. 134 aclRule, err := client.NetworkACL.CreateNetworkACL(p) 135 if err != nil { 136 ui.Error(fmt.Sprintf("Failed to create network ACL rule: %s", err)) 137 return multistep.ActionHalt 138 } 139 140 // Store the network ACL rule ID. 141 state.Put("network_acl_rule_id", aclRule.Id) 142 } else { 143 ui.Message("Creating firewall rule...") 144 145 // Create a new parameter struct. 146 p := client.Firewall.NewCreateFirewallRuleParams(config.PublicIPAddress, "TCP") 147 148 // Configure the firewall rule. 149 p.SetCidrlist(config.CIDRList) 150 p.SetStartport(s.publicPort) 151 p.SetEndport(s.publicPort) 152 153 fwRule, err := client.Firewall.CreateFirewallRule(p) 154 if err != nil { 155 ui.Error(fmt.Sprintf("Failed to create firewall rule: %s", err)) 156 return multistep.ActionHalt 157 } 158 159 // Store the firewall rule ID. 160 state.Put("firewall_rule_id", fwRule.Id) 161 } 162 163 ui.Message("Networking has been setup!") 164 165 return multistep.ActionContinue 166 } 167 168 // Cleanup any resources that may have been created during the Run phase. 169 func (s *stepSetupNetworking) Cleanup(state multistep.StateBag) { 170 client := state.Get("client").(*cloudstack.CloudStackClient) 171 ui := state.Get("ui").(packer.Ui) 172 173 ui.Say("Cleanup networking...") 174 175 if fwRuleID, ok := state.Get("firewall_rule_id").(string); ok && fwRuleID != "" { 176 // Create a new parameter struct. 177 p := client.Firewall.NewDeleteFirewallRuleParams(fwRuleID) 178 179 ui.Message("Deleting firewal rule...") 180 if _, err := client.Firewall.DeleteFirewallRule(p); err != nil { 181 // This is a very poor way to be told the ID does no longer exist :( 182 if !strings.Contains(err.Error(), fmt.Sprintf( 183 "Invalid parameter id value=%s due to incorrect long value format, "+ 184 "or entity does not exist", fwRuleID)) { 185 ui.Error(fmt.Sprintf("Error deleting firewall rule: %s", err)) 186 } 187 } 188 } 189 190 if aclRuleID, ok := state.Get("network_acl_rule_id").(string); ok && aclRuleID != "" { 191 // Create a new parameter struct. 192 p := client.NetworkACL.NewDeleteNetworkACLParams(aclRuleID) 193 194 ui.Message("Deleting network ACL rule...") 195 if _, err := client.NetworkACL.DeleteNetworkACL(p); err != nil { 196 // This is a very poor way to be told the ID does no longer exist :( 197 if !strings.Contains(err.Error(), fmt.Sprintf( 198 "Invalid parameter id value=%s due to incorrect long value format, "+ 199 "or entity does not exist", aclRuleID)) { 200 ui.Error(fmt.Sprintf("Error deleting network ACL rule: %s", err)) 201 } 202 } 203 } 204 205 if forwardID, ok := state.Get("port_forward_id").(string); ok && forwardID != "" { 206 // Create a new parameter struct. 207 p := client.Firewall.NewDeletePortForwardingRuleParams(forwardID) 208 209 ui.Message("Deleting port forward...") 210 if _, err := client.Firewall.DeletePortForwardingRule(p); err != nil { 211 // This is a very poor way to be told the ID does no longer exist :( 212 if !strings.Contains(err.Error(), fmt.Sprintf( 213 "Invalid parameter id value=%s due to incorrect long value format, "+ 214 "or entity does not exist", forwardID)) { 215 ui.Error(fmt.Sprintf("Error deleting port forward: %s", err)) 216 } 217 } 218 } 219 220 if ipAddrID, ok := state.Get("ip_address_id").(string); ok && ipAddrID != "" { 221 // Create a new parameter struct. 222 p := client.Address.NewDisassociateIpAddressParams(ipAddrID) 223 224 ui.Message("Releasing public IP address...") 225 if _, err := client.Address.DisassociateIpAddress(p); err != nil { 226 // This is a very poor way to be told the ID does no longer exist :( 227 if !strings.Contains(err.Error(), fmt.Sprintf( 228 "Invalid parameter id value=%s due to incorrect long value format, "+ 229 "or entity does not exist", ipAddrID)) { 230 ui.Error(fmt.Sprintf("Error releasing public IP address: %s", err)) 231 } 232 } 233 } 234 235 ui.Message("Networking has been cleaned!") 236 237 return 238 }