Skip to content

Commit

Permalink
adding subnets and inbound ports part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
Costya-Y committed Sep 12, 2024
1 parent 2dc8537 commit ffd0c7e
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 23 deletions.
5 changes: 1 addition & 4 deletions cloudshell/cp/gcp/actions/firewall_policy_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ class FirewallPolicyActions:
NSG_DENY_PRV_RULE_NAME_TPL = "deny_internet_traffic_to_priv_subnet_{subnet_cidr}"
VM_NSG_NAME_TPL = "rule_{vm_name}"
INBOUND_RULE_DIRECTION = "inbound"
CUSTOM_NSG_RULE_NAME_TPL = (
"rule-{vm_name}-{dst_address}-"
"{dst_port_range}-{protocol}"
)

NSG_ADD_MGMT_RULE_PRIORITY = 4000
NSG_ADD_MGMT_RULE_NAME_TPL = "allow-{mgmt_network}-to-{sandbox_cidr}"
NSG_DENY_OTHER_SB_RULE_PRIORITY = 4090
Expand Down
47 changes: 30 additions & 17 deletions cloudshell/cp/gcp/flows/deploy_instance/base_flow.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import json
import logging
from abc import abstractmethod
from typing import TYPE_CHECKING
Expand Down Expand Up @@ -42,41 +43,43 @@ def __attrs_post_init__(self):

def _prepare_vm_details_data(
self,
deployed_vm_id: int,
deploy_app: BaseGCPDeployApp
deployed_vm: InstanceHandler,
) -> VmDetailsData:
"""Prepare CloudShell VM Details model."""
vm_details_actions = VMDetailsActions(
self.proxmox_api,
self._resource_config,
self._cancellation_manager,
config=self._resource_config,
logger=self._logger,
)
return vm_details_actions.create(deployed_vm_id, deploy_app)
return vm_details_actions.prepare_vm_details(deployed_vm)

def _prepare_deploy_app_result(
self,
deploy_app: BaseGCPDeployApp,
instance_name: str,
instance_handler: InstanceHandler,
) -> DeployAppResult:
vm_details_data = self._prepare_vm_details_data(
deployed_vm_id=deployed_vm_id,
deploy_app=deploy_app,
deployed_vm=instance_handler,
)

logger.info(f"Prepared VM details: {vm_details_data}")

return DeployAppResult(
actionId=deploy_app.actionId,
vmUuid=str(deployed_vm_id),
vmName=instance_name,
vmUuid=json.dumps(
{
"instance_name": instance_handler.instance.name,
"zone": instance_handler.instance.zone
}
),
vmName=instance_handler.instance.name,
vmDetailsData=vm_details_data,
deployedAppAdditionalData={
"ip_regex": deploy_app.ip_regex,
"refresh_ip_timeout": deploy_app.refresh_ip_timeout,
"auto_power_off": deploy_app.auto_power_off,
"auto_delete": deploy_app.auto_delete,
},
deployedAppAttributes=self._prepare_app_attrs(deploy_app, deployed_vm_id),
# deployedAppAttributes=self._prepare_app_attrs(deploy_app, deployed_vm_id),
)

@abstractmethod
Expand All @@ -88,11 +91,11 @@ def _create_instance(self, deploy_app: BaseGCPDeployApp, subnet_list: list[str])
def _deploy(self, request_actions: DeployVMRequestActions) -> DeployAppResult:
"""Deploy Proxmox Instance."""
# noinspection PyTypeChecker

network_handler = self._get_network()
deploy_app: BaseGCPDeployApp = request_actions.deploy_app
subnet_list = [x.subnet_id for x in request_actions.connect_subnets]
if not subnet_list:
subnet_list = []
subnet_list = network_handler.get_subnets()

with self.cancellation_manager:
instance = self._create_instance(
Expand All @@ -102,23 +105,33 @@ def _deploy(self, request_actions: DeployVMRequestActions) -> DeployAppResult:

with self._rollback_manager:
logger.info(f"Creating Instance {instance.name}")
# ToDo DeployInstanceCommand.execute() should return InstanceHandler
# ToDo additionally we need to pass deploy_app.network_tags.keys()
deployed_instance = DeployInstanceCommand(
instance=instance,
credentials=self.resource_config.credentials,
rollback_manager=self._rollback_manager,
cancellation_manager=self.cancellation_manager,
).execute()

logger.info(f"Instance {deployed_instance.name} created")

# ToDo I will add network tags over here.
# firewall_actions = FirewallActions(config=self.config, logger=self.logger)
# for tag_name, inbound_port in deploy_app.network_tags.items():
# firewall_actions.create_inbound_port_rule(...)

logger.info(f"Preparing Deploy App result for the {deployed_instance.name}")
return self._prepare_deploy_app_result(
deploy_app=deploy_app,
instance_name=deployed_instance.name,
instance_handler=deployed_instance,
)

def _get_network(self) -> VPCHandler:
"""
Get Network.
"""

network_handler = VPCHandler.get_vpc_by_sandbox_id(self.resource_config.reservation_info.reservation_id)
return network_handler.get_vpc_by_name(network_name)
return VPCHandler.get_vpc_by_sandbox_id(
self.resource_config.reservation_info.reservation_id
)
2 changes: 1 addition & 1 deletion cloudshell/cp/gcp/handlers/vpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,4 @@ def delete(self) -> None:
logger.info(f"VPC network '{self.network.name}' deleted successfully.")

def get_subnets(self):
return self.network.subnetworks
return list(self.network.subnetworks)
77 changes: 77 additions & 0 deletions cloudshell/cp/gcp/helpers/network_tag_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import re

from attr import define

from cloudshell.cp.gcp.models.deploy_app import BaseGCPDeployApp

DEFAULT_DESTINATION = "0.0.0.0/0"
DEFAULT_PROTOCOL = "tcp"


@define
class InboundPort:
port_range: str
src_address: str = DEFAULT_DESTINATION
protocol: str = DEFAULT_PROTOCOL


@define
class NetworkTagHelper:
PORT_DATA_MATCH = re.compile(
r"^(?P<from_port>\d+)"
r"(-(?P<to_port>\d+))?"
r"(:(?P<protocol>(udp|tcp|icmp)))?"
r"(:(?P<destination>\S+))?$",
re.IGNORECASE,
)
ICMP_PORT_DATA_MATCH = re.compile(
r"^(?P<protocol>icmp)" r"(:(?P<destination>\S+))?$",
re.IGNORECASE,
)


CUSTOM_NSG_RULE_NAME_TPL = (
"rule-{vm_name}-{dst_address}-"
"{dst_port_range}-{protocol}"
)
deploy_app: BaseGCPDeployApp

def get_network_tags(self, app_name) -> dict[str,InboundPort]:
"""Get network tags for VM.
:param app_name: VM name
:return: Network tags
"""
# ToDo adjust this one for work in deploy app parser.
network_tags = {}
for network_tag in self.deploy_app.inbound_ports:
rule = self._parse_port_range(network_tag)
name = self.CUSTOM_NSG_RULE_NAME_TPL.format(
vm_name=app_name,
dst_address=rule.dst_address,
dst_port_range=rule.dst_port_range,
protocol=rule.protocol,
)
network_tags[name] = self._parse_port_range(network_tag)

return network_tags

def _parse_port_range(self, port_data):
match = self.PORT_DATA_MATCH.search(port_data)
if match:
from_port = match.group("from_port")
to_port = match.group("to_port")
else:
# match = self.ICMP_PORT_DATA_MATCH.search(port_data)
# if match:
# from_port = to_port = "-1"
# else:
msg = f"The value '{port_data}' is not a valid ports rule"
raise ValueError(msg)

destination = match.group("destination") or self.DEFAULT_DESTINATION
protocol = match.group("protocol") or self.DEFAULT_PROTOCOL
port = f"{from_port}"
if to_port:
port = f"{from_port}-{to_port}"
return InboundPort(port, protocol, destination)
18 changes: 17 additions & 1 deletion cloudshell/cp/gcp/models/deploy_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from cloudshell.cp.core.request_actions.models import DeployApp

from cloudshell.cp.gcp.helpers import constants
from cloudshell.cp.gcp.helpers.network_tag_helper import NetworkTagHelper
from cloudshell.cp.gcp.models.attributes import (
ResourceAttrRODeploymentPath,
ResourceBoolAttrRODeploymentPath,
Expand All @@ -14,6 +15,21 @@
GCPFromVMImageDeploymentAppAttributeNames,
)

CUSTOM_NSG_RULE_NAME_TPL = (
"rule-{vm_name}-{dst_address}-"
"{dst_port_range}-{protocol}"
)


class InboundPortsAttrRO(ResourceAttrRODeploymentPath):
def __get__(self, instance, owner):
if instance is None:
return self
helper = NetworkTagHelper()

attr = instance.attributes.get(self.get_key(instance), self.default)
return [port_data.strip() for port_data in attr.split(";") if port_data]


class BaseGCPDeployApp(DeployApp):
_DO_NOT_EDIT_APP_NAME = True
Expand All @@ -25,7 +41,7 @@ class BaseGCPDeployApp(DeployApp):
maintenance = ResourceAttrRODeploymentPath(ATTR_NAMES.maintenance)
auto_restart = ResourceBoolAttrRODeploymentPath(ATTR_NAMES.auto_restart)
ip_forwarding = ResourceBoolAttrRODeploymentPath(ATTR_NAMES.ip_forwarding)
inbound_ports = ResourceAttrRODeploymentPath(ATTR_NAMES.inbound_ports)
inbound_ports = InboundPortsAttrRO(ATTR_NAMES.inbound_ports)
custom_tags = ResourceAttrRODeploymentPath(ATTR_NAMES.custom_tags)
wait_for_ip = ResourceBoolAttrRODeploymentPath(ATTR_NAMES.wait_for_ip)
add_public_ip = ResourceBoolAttrRODeploymentPath(ATTR_NAMES.add_public_ip)
Expand Down

0 comments on commit ffd0c7e

Please sign in to comment.