Google Compute API: new instance with external IP - google-api

I'm trying to dynamically create Compute instances on Google Cloud via PHP using API.
Using csmartinez Cloud API sample, I managed to create my instance and can see it running on Google Console.
I need to assign an external IP address to this newly created instance. Based on the API and Google PHP library, I then added:
$ipName = "foo";
$addr = new Google_Service_Compute_Address();
$addr->setName($ipName);
$response = $service->addresses->insert($project, $ipZone, $addr);
Since this call has a "pending" status at first, I added a sleep(5) so I can then get the newly created static IP:
$response = $service->addresses->get($project, $ipZone, $ipName);
$ip = $response->address;
which runs well and gives me the correct IP address. I then continue and try to create my instance while assigning the new IP:
$networkConfig = new Google_Service_Compute_AccessConfig();
$networkConfig->setNatIP($ip);
$networkConfig->setType("ONE_TO_ONE_NAT");
$networkConfig->setName("External NAT");
$googleNetworkInterfaceObj->setAccessConfigs($networkConfig);
The static IP is created, the instance is created, but IP is not assigned to the instance.
To remove my doubt about the pending status, I also tried to assign an already created static IP to my instance, thus using:
$networkConfig->setNatIP("xxx.xxx.xxx.xxx");
With no more success... What am I missing here ?

I think this line:
$googleNetworkInterfaceObj->setAccessConfigs($networkConfig);
should be:
$googleNetworkInterfaceObj->setAccessConfigs(array($networkConfig));
If this doesn't work, there might be another error somewhere else.

this would be the whole procedure, which assigns a network:
$instance = new Google_Instance();
$instance->setKind("compute#instance");
$accessConfig = new Google_AccessConfig();
$accessConfig->setName("External NAT");
$accessConfig->setType("ONE_TO_ONE_NAT");
$network = new Google_NetworkInterface();
$network->setNetwork($this->getObjectUrl($networkName, 'networks', $environment->getPlatformConfigValue(self::PROJECT_ID)));
$network->setAccessConfigs(array($accessConfig));
$instance->setNetworkInterfaces(array($network));
$addr->setName() is barely cosmetic; try $addr->setAddress($ipAddress).
guess the Google_NetworkInterface would need the $addr assigned.
sorry, currently have no spare IP and do not want to pay only to provide code.

Related

JClouds: How Do You Ask For an AWS-EC2 Public IP Address

When using Apache JClouds, how do you get launch a compute instance with a public IP? This is different from an elastic IP. Using the official AWS API you can do something like:
//create network information
InstanceNetworkInterfaceSpecification networkWithPublicIp = new InstanceNetworkInterfaceSpecification()
.withSubnetId(subnetId)
.withAssociatePublicIpAddress(true)
.withGroups( securityGroupIds )
.withDeviceIndex(0);
Once the node is launched, it will have a randomly assigned public IP (not elastic). Is there a way to do this with Jclouds and AWSEC2TemplateOptions?
There is an example in the doc at http://jclouds.apache.org/guides/aws/
// ex. to get an ip and associate it with a node
String ip = ec2Client.getElasticIPAddressServices().allocateAddressInRegion(node.getLocation().getId());
ec2Client.getElasticIPAddressServices().associateAddressInRegion(node.getLocation().getId(),ip, node.getProviderId());

how to get an aws instance given I have the instance's ip

Given I have an aws instance IP, how can I get the EC2 instance collection object via the ruby aws-sdk's filter option. For example
#ec2.instances.filter(valid_filter_name, ec2_instance_ip)
I've tried 'public_ip_address' and 'public_ip' as the filter name but those didn't work. I'm using this API doc http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/FilteredCollection.html#filter-instance_method, but it's does not mentioned what the valid parameters are.
It turns out the correct parameter to use (by trial & error) is 'ip-address'. Here's an example:
#ec2.instances.filter('ip-address', ec2_instance_ip)

Selective cache clearing from models with sfMemcache

I have a multilingual site (culture depends on the host URL eg.: uk.site.com, fr.site.com etc.). I'm caching a partial in the frontend and set its cache key. Then from the model I do something like:
$cacheManager = sfContext::getInstance()->getViewCacheManager();
$cacheUri = $cacheManager->getPartialUri($module, $action, $cacheKey);
$cacheManager->remove($cacheUri, *); //second param is to clear this cache for all hosts
// $cacheManager->remove($cacheUri); when is like that it works for fine but only for the domain it's been called from.
The code above calls the sf core method sfMemCache->removePattern($pattern) which has:
$regexp = self::patternToRegexp($this->getOption('prefix').$pattern);
foreach ($this->getCacheInfo() as $key)
{
if (preg_match($regexp, $key))
{
$this->remove(substr($key, strlen($this->getOption('prefix'))));
}
}
and $this->getCacheInfo() is always empty and it can't clear anything.
It always throw "To use the "removePattern" method, you must set the "storeCacheInfo" option to "true"." exception. I cant find where does that cacheInfos() has to be filled or what exactly is its role.
Simplified version of my question is: "Why is $this->getCacheInfo empty"
If the removePattern method is throwing that error then memcached is not configured correctly in your factories.yml configuration.
The answer you want is discussed on this page under the heading 'Alternative Caching storage'
You need to set your class and parameter correctly to use the removePattern method. For instance:
view_cache:
class: sfMemcacheCache
param:
host: localhost
port: 11211
persistent: true
storeCacheInfo: true
You will also need to insure that the memcached daemon is operational. If memcached is running on the same host as the script in it's default configuration then the above settings should be fine. If you are running memcached on a separate host or you have multiple hosts sharing a memcached service then you must insure your host, port and firewall settings are correct for your environment.

The specified format name does not support the requested operation. For example, a direct queue format name cannot be deleted

I'm trying to send a message to a queue using a Message object and am getting the error
The specified format name does not support the requested operation. For example, a direct queue format name cannot be deleted.
Here is the code.
Order ord = new Order(new Guid(), "Smith & Smith");
Message orderMessage = new Message(ord);
orderMessage.UseEncryption = true;
orderMessage.EncryptionAlgorithm = EncryptionAlgorithm.Rc2;
orderMessage.Recoverable = true;
orderMessage.Priority = MessagePriority.VeryHigh;
orderMessage.TimeToBeReceived = TimeSpan.FromHours(1);
orderMessage.UseJournalQueue = true;
orderMessage.Body = "Test Encryption";
queue.Send(orderMessage, "Encrypted Order");
Any help with this is appreciated.
Tom
Did you ever solve this? I came across this problem myself and found out I needed to use (just like the error says) a different format name.
The strange thing was that if I set UseAuthentication property using the MQ certificate, then it worked. But if I also wanted to set UseEncryption, then it did not work.
You do not specify your queue/server setup/formats, but I suspect you're trying to send from one machine to another machine's public queue within the same domain, using DIRECT formatname? As the MQ Manager will use the domain AD to lookup the certificate and queue details, it raises an exception as the format name is invalid (not the same as specified in the AD). So instead of using the direct format, use the queue ID to define the formatname. I switched this:
"FormatName:Direct=TCP:111.222.1.22\your_public_queue"
with this:
"FormatName:PUBLIC=7EB2A53C-7593-462C-A568-5A0EFA26D91D"
Now it worked. You can find your queue ID by right-clicking your queue on the receiver machine and then go to Properties->General and see the value specified in field "ID".
I have found that getting the FormatName correct whether public or private in nature will save hours of work. It's incredibly important to understand the setup of each (Public requiring AD and private does not when access remotely). This is a great summary of FormatName.
https://blogs.msdn.microsoft.com/johnbreakwell/2009/02/26/difference-between-path-name-and-format-name-when-accessing-msmq-queues/
One note on this issue, if your queue format name starts this way: "FormatName:Direct=" then you will receive the error "The specified format name does not support the requested operation. For example, a direct queue format name cannot be deleted" if you try to access the queue's QueueName property. Use the queue's FormatName property instead.

Updating an AutoScalingGroup with a new LaunchConfiguration in boto

I have a script that needs to update a named AutoScalingGroup with a new LaunchConfiguration for some new just-created AMI. Unfortunately the documentation isn't good, and I'm tired of trial-and-error. This is what I have so far:
build_autoscale_name = "build_autoscaling"
build_autoscale_lc = LaunchConfiguration(
...launch config stuff...
, image_id=imid # new AMI
)
as_conn.create_launch_configuration(build_autoscale_lc)
ag = AutoScalingGroup(
group_name=build_autoscale_name
, launch_config=build_autoscale_lc
...other ASG stuff...
)
as_conn.create_auto_scaling_group(ag)
The latest way this is failing is with:
Launch Configuration by this name already exists
If I comment out the create_launch_configuration() I then get:
AutoScalingGroup by this name already exists
I see AutoScalingGroup has an update method; do I need to perhaps get_all_groups() then do update with a new LaunchConfiguration with the same name? Or does it matter if I create a newly-named LaunchConfiguration every time (i.e. will I run into some limit)?
I was experiencing a similar problem, when trying to update an existing autoscaling group, and managed to sort it out with the the process you suggested in your original post: using get_all_groups() to fetch the autoscaling group, and then calling update() on the object after updating the attributes.
Full example:
autoscaling_group_name = 'my-test-asg'
launch_config_name = 'my-test-lc'
launch_config = LaunchConfiguration( name=launch_config_name,
image_id=image_id,
key_name=ssh_key_name,
security_groups=security_groups,
user_data=user_data,
instance_type=instance_type,
associate_public_ip_address=associate_public_ip )
as_group = as_conn.get_all_groups(names=[autoscaling_group_name])[0]
setattr(as_group, launch_config_name, launch_config)
as_group.update()
I am not familiar with boto, but I can clear few doubts about autoscaling in AWS. To update launch configuration of an autoscaling group you will have to create a new launch configuration and update the launch config for autoscaling group. You can either keep two names for launchconfig. So if the first name is in use then delete the launch config with the second name and create a new one with the second name after that update autoscaling group and same if launchconfig in use has the second name. So, you will have only two launch configs at a time.
Hope I have understood you problem correctly.

Resources