def _add_ingress_rule(self, args, security_group): """ Add a local -> PostgreSQL ingress rule to a security group """ ec2 = self._get_aws_client('ec2', args) ip = args.public_ip if args.public_ip else\ '{}/32'.format(get_my_ip()) port = args.db_port or 5432 IpRanges = [] ip = ip.split(',') for i in ip: IpRanges.append({ 'CidrIp': i, 'Description': 'pgcloud client {}'.format(i) }) try: output({'Adding': 'Adding ingress rule for: {}...'.format(ip)}) debug(args, 'Adding ingress rule for: {}...'.format(ip)) ec2.authorize_security_group_ingress(GroupId=security_group, IpPermissions=[ { 'FromPort': port, 'ToPort': port, 'IpProtocol': 'tcp', 'IpRanges': IpRanges }, ]) except Exception as e: error(args, e)
def _create_firewall_rule(self, args): """ Create a firewall rule on an instance """ firewall_rules = [] postgresql_client = self._get_azure_client('postgresql') ip = args.public_ips if args.public_ips else get_my_ip() ip_list = ip.split(',') for ip in ip_list: ip = ip.strip() if '-' in ip: start_ip = ip.split('-')[0] end_ip = ip.split('-')[1] else: start_ip = ip end_ip = ip name = 'pgacloud_{}_{}_{}'.format(args.name, ip.replace('.', '-'), get_random_id()) # Provision the rule and wait for completion debug('Adding ingress rule for: {0} - {1} ...'.format( start_ip, end_ip)) poller = postgresql_client.firewall_rules.begin_create_or_update( resource_group_name=args.resource_group, server_name=args.name, firewall_rule_name=name, parameters=FirewallRule(start_ip_address=start_ip, end_ip_address=end_ip)) firewall_rule = poller.result() firewall_rules.append(firewall_rule.__dict__) return firewall_rules
def _delete_security_group(self, args, id): """ Delete a security group """ ec2 = self._get_aws_client('ec2', args) debug(args, 'Deleting security group: {}...'.format(id)) try: ec2.delete_security_group(GroupId=id) except Exception as e: error(args, str(e))
def _delete_azure_instance(self, args): """ Delete an Azure instance """ # Obtain the management client object postgresql_client = self._get_azure_client('postgresql') # Delete the server and wait for the result debug('Deleting Azure instance: {}...'.format(args.name)) try: poller = postgresql_client.servers.begin_delete( args.resource_group, args.name) except Exception as e: error(str(e)) poller.result()
def _create_resource_group(self, args): """ Create the Resource Group if it doesn't exist """ resource_client = self._get_azure_client('resource') group_list = resource_client.resource_groups.list() for group in list(group_list): if group.name == args.resource_group: debug('Resource group already exist with name: {}...'.format( args.resource_group)) return group.__dict__ debug('Creating resource group with name: {}...'.format( args.resource_group)) result = resource_client.resource_groups.create_or_update( args.resource_group, {"location": args.region}) return result.__dict__
def _create_azure_instance(self, args): """ Create an Azure instance """ # Obtain the management client object postgresql_client = self._get_azure_client('postgresql') # Check if the server already exists svr = None try: svr = postgresql_client.servers.get(args.resource_group, args.name) except ResourceNotFoundError: pass except Exception as e: error(str(e)) if svr is not None: error('Azure Database for PostgreSQL instance {} already ' 'exists.'.format(args.name)) db_password = self._database_pass if self._database_pass is not None \ else args.db_password # Provision the server and wait for the result debug('Creating Azure instance: {}...'.format(args.name)) try: poller = postgresql_client.servers.begin_create( resource_group_name=args.resource_group, server_name=args.name, parameters=Server( sku=Sku(name=args.instance_type, tier=SkuTier(args.instance_tier_type)), high_availability=HighAvailability( mode=args.high_availability), administrator_login=args.db_username, administrator_login_password=db_password, version=args.db_major_version, storage=Storage(storage_size_gb=args.storage_size), location=args.region, create_mode=CreateMode("Default"))) except Exception as e: error(str(e)) server = poller.result() return server.__dict__
def _create_security_group(self, args): """ Create a new security group for the instance """ ec2 = self._get_aws_client('ec2', args) ip = args.public_ip if args.public_ip else get_my_ip() ip = ip.split(',') # Deploy the security group try: name = 'pgacloud_{}_{}_{}'.format(args.name, ip[0].replace('.', '-'), get_random_id()) debug(args, 'Creating security group: {}...'.format(name)) output({'Creating': 'Creating security group: {}...'.format(name)}) response = ec2.create_security_group( Description='Inbound access for {} to RDS instance {}'.format( ip[0], args.name), GroupName=name) except Exception as e: error(args, str(e)) return response['GroupId']
def _delete_rds_instance(self, args, name): """ Delete an RDS instance """ rds = self._get_aws_client('rds', args) debug(args, 'Deleting RDS instance: {}...'.format(name)) try: rds.delete_db_instance(DBInstanceIdentifier=name, SkipFinalSnapshot=True, DeleteAutomatedBackups=True) except Exception as e: error(args, str(e)) # Wait for completion while True: try: rds.describe_db_instances(DBInstanceIdentifier=args.name) except rds.exceptions.DBInstanceNotFoundFault: return except Exception as e: error(args, str(e)) time.sleep(5)
def _create_rds_instance(self, args, security_group): """ Create an RDS instance """ ec2 = self._get_aws_client('ec2', args) rds = self._get_aws_client('rds', args) db_password = self._database_pass if self._database_pass is not None\ else args.db_password try: debug(args, 'Creating RDS instance: {}...'.format(args.name)) rds.create_db_instance(DBInstanceIdentifier=args.name, AllocatedStorage=args.storage_size, DBName=args.db_name, Engine='postgres', Port=args.db_port, EngineVersion=args.db_version, StorageType=args.storage_type, StorageEncrypted=True, Iops=args.storage_iops, AutoMinorVersionUpgrade=True, MultiAZ=False, MasterUsername=args.db_username, MasterUserPassword=db_password, DBInstanceClass=args.instance_type, VpcSecurityGroupIds=[ security_group, ]) except rds.exceptions.DBInstanceAlreadyExistsFault as e: try: debug(args, DEL_SEC_GROUP_MSG.format(security_group)) ec2.delete_security_group(GroupId=security_group) except Exception: pass error(args, 'RDS instance {} already exists.'.format(args.name)) except Exception as e: try: debug(args, DEL_SEC_GROUP_MSG.format(security_group)) ec2.delete_security_group(GroupId=security_group) except Exception: pass error(args, str(e)) # Wait for completion running = True while running: response = rds.describe_db_instances( DBInstanceIdentifier=args.name) db_instance = response['DBInstances'][0] status = db_instance['DBInstanceStatus'] if status != 'creating' and status != 'backing-up': running = False if running: time.sleep(5) return response['DBInstances']
def get_instance_status(self, instance_id): """ Get the biganimal cluster status """ running = True status = None while running: _url = "{0}/{1}/{2}".format(self.BASE_URL, 'clusters', instance_id) _headers = { "accept": "application/json", 'authorization': 'Bearer {0}'.format(self._access_key) } cluster_resp = requests.get(_url, headers=_headers) if cluster_resp.status_code == 200 and cluster_resp.content: cluster_info = json.loads(cluster_resp.content) self._cluster_info = cluster_info[0] if self._cluster_info['instance'] != 0 and\ self._cluster_info['phase'] not in [ 'Cluster creation request received', 'Setting up primary', 'Creating CNP cluster' ]: running = False if status != self._cluster_info['phase']: status = self._cluster_info['phase'] debug('BigAnimal cluster status: {}...'.format(status)) else: running = False error(str(cluster_resp.text)) if running: time.sleep(5) return self._cluster_info
def cmd_create_instance(self, args): """ Create a biganimal cluster """ try: private_network = True if args.private_network == '1' else False ip = args.public_ip if args.public_ip else '0.0.0.0/0' ip_ranges = [] ip = ip.split(',') for i in ip: ip_ranges.append([i, 'pgcloud client {}'.format(i)]) debug('Creating BigAnimal cluster: {}...'.format(args.name)) _url = "{0}/{1}".format(self.BASE_URL, 'clusters') _headers = { "content-type": "application/json", "accept": "application/json", 'authorization': 'Bearer {0}'.format(self._access_key) } _data = { 'clusterName': args.name, 'instanceTypeId': args.instance_type, 'password': self._database_pass, 'postgresTypeId': args.db_type, 'postgresVersion': args.db_version, 'privateNetworking': private_network, 'providerId': 'azure', 'regionId': args.region, 'replicas': 3, 'volumePropertiesId': args.volume_properties, 'volumeTypeId': args.volume_type, 'clusterArch': { 'id': args.cluster_arch, 'nodes': int(args.nodes) }, 'pgConfigMap': [], } if not private_network: _data['allowIpRangeMap'] = ip_ranges cluster_resp = requests.post(_url, headers=_headers, data=json.dumps(_data)) if cluster_resp.status_code == 202 and cluster_resp.content: cluster_info = json.loads(cluster_resp.content) instance_id = cluster_info['pgId'] instance = self.get_instance_status(instance_id) data = { 'instance': { 'ImageName': instance['imageName'], 'Database Type': instance['pgType']['name'], 'Hostname': instance['clusterConnectionInfo']['serviceName'], 'Port': instance['clusterConnectionInfo']['port'], 'Database': instance['clusterConnectionInfo']['databaseName'], 'Username': instance['clusterConnectionInfo']['username'] } } output(data) else: error(str(cluster_resp.text)) except Exception as e: debug(str(e))