Merge pull request #1474 from remibergsma/47_private_gw_initial_config

Handle private gateways more reliablyWhen initialising a VPC router we need to know which IP/device corresponds to a private gateway. This is to solve a problem when stop/starting a VPC router (which gets the private gateway config as a guest network and as a result breaks the functionality). You read it right, the private gateway is sent as type=guest after reboot and type=public initially.

Before this change, you could add a private gw to a running router but you couldn't restart it (it would mix up the tiers). Now the private gateway is detected properly and it works just fine.

Booting without private gateway:
```
root@r-167-VM:~# cat /etc/cloudstack/cmdline.json
{
    "config": {
        "baremetalnotificationapikey": "V2l1u3wKJVan01h8kq63-5Y5Ia3VLEW1v_Z6i-31QIRJXlt5vkqaqf6DVcdK0jP3u79SW6X9pqJSLSwQP2c2Rw",
        "baremetalnotificationsecuritykey": "OXI16srCrxFBi-xOtEwcYqwLlMfSFTlTg66YHtXBBqR7HNN1us3HP5zWOKxfVmz4a3C1kUNLPrUH13gNmZlu4w",
        "disable_rp_filter": "true",
        "dns1": "8.8.8.8",
        "domain": "cs2cloud",
        "eth0ip": "169.254.0.42",
        "eth0mask": "255.255.0.0",
        "host": "192.168.22.61",
        "name": "r-167-VM",
        "port": "8080",
        "privategateway": "None",
        "redundant_router": "false",
        "template": "domP",
        "type": "vpcrouter",
        "vpccidr": "10.0.0.0/24"
    },
    "id": "cmdline"
```

Booting with private gateway:
```
root@r-167-VM:~# cat /etc/cloudstack/cmdline.json
{
    "config": {
        "baremetalnotificationapikey": "V2l1u3wKJVan01h8kq63-5Y5Ia3VLEW1v_Z6i-31QIRJXlt5vkqaqf6DVcdK0jP3u79SW6X9pqJSLSwQP2c2Rw",
        "baremetalnotificationsecuritykey": "OXI16srCrxFBi-xOtEwcYqwLlMfSFTlTg66YHtXBBqR7HNN1us3HP5zWOKxfVmz4a3C1kUNLPrUH13gNmZlu4w",
        "disable_rp_filter": "true",
        "dns1": "8.8.8.8",
        "domain": "cs2cloud",
        "eth0ip": "169.254.2.227",
        "eth0mask": "255.255.0.0",
        "host": "192.168.22.61",
        "name": "r-167-VM",
        "port": "8080",
        "privategateway": "10.201.10.1",
        "redundant_router": "false",
        "template": "domP",
        "type": "vpcrouter",
        "vpccidr": "10.0.0.0/24"
    },
    "id": "cmdline"
```

And:
```
cat cmdline
vpccidr=10.0.0.0/24 domain=cs2cloud dns1=8.8.8.8 privategateway=10.201.10.1 template=domP name=r-167-VM eth0ip=169.254.2.227 eth0mask=255.255.0.0 type=vpcrouter disable_rp_filter=true baremetalnotificationsecuritykey=OXI16srCrxFBi-xOtEwcYqwLlMfSFTlTg66YHtXBBqR7HNN1us3HP5zWOKxfVmz4a3C1kUNLPrUH13gNmZlu4w baremetalnotificationapikey=V2l1u3wKJVan01h8kq63-5Y5Ia3VLEW1v_Z6i-31QIRJXlt5vkqaqf6DVcdK0jP3u79SW6X9pqJSLSwQP2c2Rw host=192.168.22.61 port=8080
```

Logs:
```
2016-02-24 20:08:45,723 DEBUG [c.c.n.r.VpcVirtualNetworkApplianceManagerImpl] (Work-Job-Executor-4:ctx-458d4c52 job-1402/job-1403 ctx-d5355fca) (logid:5772906c) Set privategateway field in cmd_line.json to 10.201.10.1
```

* pr/1474:
  Handle private gateways more reliably
  Add private gateway IP to router initialization config

Signed-off-by: Will Stevens <williamstevens@gmail.com>
This commit is contained in:
Will Stevens 2016-05-12 11:02:55 -04:00
commit 3fab75772f
3 changed files with 57 additions and 1 deletions

View File

@ -65,6 +65,7 @@ import com.cloud.network.vpc.StaticRoute;
import com.cloud.network.vpc.StaticRouteProfile;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcGateway;
import com.cloud.network.vpc.VpcGatewayVO;
import com.cloud.network.vpc.VpcManager;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.PrivateIpDao;
@ -260,6 +261,15 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian
if (defaultDns2 != null) {
buf.append(" dns2=").append(defaultDns2);
}
VpcGatewayVO privateGatewayForVpc = _vpcGatewayDao.getPrivateGatewayForVpc(domainRouterVO.getVpcId());
if (privateGatewayForVpc != null) {
String ip4Address = privateGatewayForVpc.getIp4Address();
buf.append(" privategateway=").append(ip4Address);
s_logger.debug("Set privategateway field in cmd_line.json to " + ip4Address);
} else {
buf.append(" privategateway=None");
}
}
}

View File

@ -248,4 +248,4 @@ def copy(src, dest):
except IOError:
logging.Error("Could not copy %s to %s" % (src, dest))
else:
logging.info("Copied %s to %s" % (src, dest))
logging.info("Copied %s to %s" % (src, dest))

View File

@ -145,10 +145,13 @@ class updateDataBag:
dp['gateway'] = d['router_guest_gateway']
dp['nic_dev_id'] = d['device'][3]
dp['nw_type'] = 'guest'
dp = PrivateGatewayHack.update_network_type_for_privategateway(dbag, dp)
qf = QueueFile()
qf.load({'ip_address': [dp], 'type': 'ips'})
if 'domain_name' not in d.keys() or d['domain_name'] == '':
d['domain_name'] = "cloudnine.internal"
d = PrivateGatewayHack.update_network_type_for_privategateway(dbag, d)
return cs_guestnetwork.merge(dbag, d)
def process_dhcp_entry(self, dbag):
@ -274,3 +277,46 @@ class QueueFile:
os.makedirs(path)
timestamp = str(int(round(time.time())))
os.rename(origPath, path + "/" + self.fileName + "." + timestamp)
class PrivateGatewayHack:
@classmethod
def update_network_type_for_privategateway(cls, dbag, data):
ip = data['router_guest_ip'] if 'router_guest_ip' in data.keys() else data['public_ip']
initial_data = cls.load_inital_data()
has_private_gw_ip = cls.if_config_has_privategateway(initial_data)
private_gw_matches = 'privategateway' in initial_data['config'] and cls.ip_matches_private_gateway_ip(ip, initial_data['config']['privategateway'])
if has_private_gw_ip and private_gw_matches:
data['nw_type'] = "public"
logging.debug("Updating nw_type for ip %s" % ip)
else:
logging.debug("Not updating nw_type for ip %s because has_private_gw_ip = %s and private_gw_matches = %s " % (ip, has_private_gw_ip, private_gw_matches))
return data
@classmethod
def if_config_has_privategateway(cls, dbag):
return 'privategateway' in dbag['config'].keys() and dbag['config']['privategateway'] != "None"
@classmethod
def ip_matches_private_gateway_ip(cls, ip, private_gateway_ip):
new_ip_matches_private_gateway_ip = False
if ip == private_gateway_ip:
new_ip_matches_private_gateway_ip = True
return new_ip_matches_private_gateway_ip
@classmethod
def load_inital_data(cls):
initial_data_bag = DataBag()
initial_data_bag.setKey('cmdline')
initial_data_bag.load()
initial_data = initial_data_bag.getDataBag()
logging.debug("Initial data = %s" % initial_data)
return initial_data